Python read-only property

Rafał Łużyński picture Rafał Łużyński · Jan 30, 2013 · Viewed 111.2k times · Source

I don't know when attribute should be private and if I should use property.

I read recently that setters and getters are not pythonic and I should use property decorator. It's ok.

But what if I have attribute, that mustn't be set from outside of class but can be read (read-only attribute). Should this attribute be private, and by private I mean with underscore, like that self._x? If yes then how can I read it without using getter? Only method I know right now is to write

@property
def x(self):
    return self._x

That way I can read attribute by obj.x but I can't set it obj.x = 1 so it's fine.

But should I really care about setting object that mustn't be set? Maybe I should just leave it. But then again I can't use underscore because reading obj._x is odd for user, so I should use obj.x and then again user doesn't know that he mustn't set this attribute.

What's your opinion and practics?

Answer

siebz0r picture siebz0r · Apr 4, 2013

Just my two cents, Silas Ray is on the right track, however I felt like adding an example. ;-)

Python is a type-unsafe language and thus you'll always have to trust the users of your code to use the code like a reasonable (sensible) person.

Per PEP 8:

Use one leading underscore only for non-public methods and instance variables.

To have a 'read-only' property in a class you can make use of the @property decoration, you'll need to inherit from object when you do so to make use of the new-style classes.

Example:

>>> class A(object):
...     def __init__(self, a):
...         self._a = a
...
...     @property
...     def a(self):
...         return self._a
... 
>>> a = A('test')
>>> a.a
'test'
>>> a.a = 'pleh'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute