7

I know that it is not pythonic to use getters and setters in python. Rather property decorators should be used. But I am wondering about the following scenario -

I have a class initialized with a few instance attributes. Then later on I need to add other instance attributes to the class. If I don't use setters, then I have to write object.attribute = value everywhere outside the class. The class will not have the self.attribute code. Won't this become a problem when I need to track the attributes of the class (because they are strewn all over the code outside the class)?

debashish
  • 1,374
  • 1
  • 19
  • 29
  • I think you should read this article regarding your subject: http://www.python-course.eu/python3_properties.php ALso, worth reading: http://stackoverflow.com/questions/2627002/whats-the-pythonic-way-to-use-getters-and-setters Just another one, that is quite good. A must, I may say: http://stackoverflow.com/questions/6618002/python-property-versus-getters-and-setters – FSRubyc May 10 '17 at 15:32

1 Answers1

7

In general, you shouldn't even use properties. Simple attributes work just fine in the vast majority of cases:

class X:
    pass

>>> x = X()
>>> x.a
Traceback (most recent call last):
  # ... etc
AttributeError: 'X' object has no attribute 'a'
>>> x.a = 'foo'
>>> x.a
'foo'

A property should only be used if you need to do some work when accessing an attribute:

import random

class X:

    @property
    def a(self):
        return random.random()

>>> x = X()
>>> x.a
0.8467160913203089

If you also need to be able to assign to a property, defining a setter is straightforward:

class X:

    @property
    def a(self):
        # do something clever
        return self._a

    @a.setter
    def a(self, value):
        # do something even cleverer
        self._a = value

>>> x = X()
>>> x.a
Traceback (most recent call last):
  # ... etc
AttributeError: 'X' object has no attribute '_a'
>>> x.a = 'foo'
>>> x.a
'foo'

Notice that in each case, the way that client code accesses the attribute or property is exactly the same. There's no need to "future-proof" your class against the possibility that at some point you might want to do something more complex than simple attribute access, so no reason to write properties, getters or setters unless you actually need them right now.

For more on the differences between idiomatic Python and some other languages when it comes to properties, getters and setters, see:

Zero Piraeus
  • 56,143
  • 27
  • 150
  • 160
  • What do you mean exactly by "A property should only be used if you need to do some work when accessing an attribute:" ? – guy Mar 13 '18 at 12:58
  • @guy it seems self-explanatory to me in the context of the answer as a whole ... what do you find confusing about it, may I ask? – Zero Piraeus Mar 13 '18 at 13:01
  • I'm struggling to determine when to use / not use the @property decorator. I thought it automatically made an attribute read-only but it seems like it is not the case. I also thought that if you have an attribute that is calculated from other attributes then you want this decorator but I don't know why..... – guy Mar 13 '18 at 13:06
  • 2
    @guy Without a setter, a property does look like a read-only attribute from the outside, but that's not what it's *for*, and in fact the idea of deliberately making an attribute read-only goes against Python's "consenting adults" philosophy in any case. Properties are, as you say, meant for attributes that require some computation to happen while accessing them. A complete tutorial on their purpose and use is out of scope for this answer; apart from the links I already gave, maybe [this article](https://www.blog.pythonlibrary.org/2014/01/20/python-201-properties/) will be useful to you. – Zero Piraeus Mar 13 '18 at 13:22