How do Python properties work?
As others have noted, they use a language feature called descriptors.
The reason that the actual property object is returned when you access it via a class Foo.hello
lies in how the property implements the __get__(self, instance, owner)
special method:
- If a descriptor is accessed on an instance, then that instance is passed as the appropriate argument, and
owner
is the class of that instance. - When it is accessed through the class, then
instance
is None and onlyowner
is passed. Theproperty
object recognizes this and returnsself
.
Besides the Descriptors howto, see also the documentation on Implementing Descriptors and Invoking Descriptors in the Language Guide.
In order for @properties to work properly the class needs to be a subclass of object. when the class is not a subclass of object then the first time you try access the setter it actually makes a new attribute with the shorter name instead of accessing through the setter.
The following does not work correctly.
class C(): # <-- Notice that object is missing def __init__(self): self._x = None @property def x(self): print 'getting value of x' return self._x @x.setter def x(self, x): print 'setting value of x' self._x = x>>> c = C()>>> c.x = 1>>> print c.x, c._x1 0
The following will work correctly
class C(object): def __init__(self): self._x = None @property def x(self): print 'getting value of x' return self._x @x.setter def x(self, x): print 'setting value of x' self._x = x>>> c = C()>>> c.x = 1setting value of x>>> print c.x, c._xgetting value of x1 1
Properties are descriptors, and descriptors behave specially when member of a class instance. In short, if a
is an instance of type A
, and A.foo
is a descriptor, then a.foo
is equivalent to A.foo.__get__(a)
.