20

Is this how you would define a class "Car" with attribute "Speed" in Python? My background is in Java, and it seems one does not use get/set methods in Python.

class Car(object):
    def __init__(self):
        self._speed = 100

    @property
    def speed(self):
        return self._speed

    @speed.setter
    def speed(self, value):
        self._speed = value
lol
  • 203
  • 1
  • 2
  • 4
  • 1
    In Python you usually do not use get/set accessors, you directly change/get the object value. You have used underscore before variable name-why do you want to use private variable? This is generally not the ,,pythonic'' way. See here for more information: http://stackoverflow.com/questions/551038/private-implementation-class-in-python – Wookie88 Mar 29 '13 at 16:14

3 Answers3

28

In Python we generally avoid getters and setters. Just have a .speed attribute:

class Car(object):
    speed = 0

    def __init__(self):
        self.speed = 100

See Python is not Java for motivations and more pitfalls to avoid:

In Java, you have to use getters and setters because using public fields gives you no opportunity to go back and change your mind later to using getters and setters. So in Java, you might as well get the chore out of the way up front. In Python, this is silly, because you can start with a normal attribute and change your mind at any time, without affecting any clients of the class. So, don't write getters and setters.

Use property when you have a genuine need to execute code when getting, setting or deleting an attribute. Validation, caching, side effects, etc. all are fair use-cases for properties. Just don't use them until necessary.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • If I should add some validation, e.g. check that speed is between 0.100, would then go with my example? – lol Mar 29 '13 at 16:22
  • 2
    Yes, I'd say a property would be the right way to go in that case. – Kyle Strand Mar 29 '13 at 16:23
  • 1
    @lol: Validation is a valid usecase for using a `@property`. – Martijn Pieters Mar 29 '13 at 16:25
  • One more question: when using the @property, should the variable be declared as self.speed or self._speed? Thank you for replies (: – lol Mar 29 '13 at 16:29
  • 1
    @lol: Anything that is different from the property name. Using `_speed` is a good convention; the leading `_` documents it is a private attribute, and it won't clash with the property name. – Martijn Pieters Mar 29 '13 at 16:31
  • ah, yes, ok. I did not yet get there would be a name conflict (of course there is, since the variable is public) – lol Mar 29 '13 at 16:33
  • 4
    Doesn't this actually declare a class attribute, not an instance attribute? – Zoltán Dec 19 '13 at 03:08
  • 1
    We create *both*. The `speed = 0` line is a class attribute. Setting `self.speed` in a method sets a instance attribute. Setting an attribute on an instance *never* sets the class attribute, even if one exists. This makes a class attribute a great way to specify a default; if no instance attribute is set, *reading* an attribute on a class will return the class attribute instead. – Martijn Pieters Dec 19 '13 at 03:15
  • 2
    @MartijnPieters So why do you define the class attribute? – binki Nov 27 '16 at 19:55
  • @binki: as an illustration; with `__init__` setting it unconditionally it is ignored on instance attribute access, but `Car.speed` works and provides the default. – Martijn Pieters Nov 27 '16 at 22:14
1

Since technically attributes are never private in Python, get/set methods are not considered "pythonic." This is the standard way to access object attributes:

class MyClass():
    def __init__(self):
        self.my_attr = 3

obj1 = MyClass()
print obj1.my_attr #will print 3
obj1.my_attr = 7
print obj1.my_attr #will print 7

You may, of course, still use getters and setters, and you can somewhat emulate private members by prepending __ to your attributes:

class MyClass():
    def __init__(self):
        self.__my_attr = 3
    def set_my_attr(self,val):
        self.__my_attr = val
    def get_my_attr(self):
        return self.__my_attr

obj1 = MyClass()
print obj1.get_my_attr() #will print 3
obj1.set_my_attr(7)
print obj1.get_my_attr() #will print 7

The __ "mangles" the variable name: from outside some class classname in which __attr is defined, __attr is renamed as _classname__attr; in the above example, instead of using the getters and setters, we could simply use obj1._MyClass__my_attr. So __ discourages external use of attributes, but it doesn't prohibit it in the same way that the Java private modifier does.

There are also, as you mention in your question, properties available in Python. The advantage of properties is that you can use them to implement functions that return or set values that, from outside the class, appear to be simply accessed as normal member attributes.

Kyle Strand
  • 15,941
  • 8
  • 72
  • 167
0

I would go for attributes, like that:

class Car(object):
    def __init__(self):
        self.speed = 100

where you can change and get it exactly the same way. The @property notation is probably more of use for wrapping classes that use Java/C get/set methods, virtual attributes or if you need to manipulate the values being entered.

I use that often in GUI classes where I can easily force redrawing of the screen based on changing attributes of widgets, sort of a custom events system.

unddoch
  • 5,790
  • 1
  • 24
  • 37