-
28 April 2010, 00:35
Python Properties
When just getting started with Python, it may seem odd that everything is public in Python. Well, yes, everything is public, but there are conventions to denote that something is internal only and should not be accessed outside the scope of the class or module. Anything with a leading underscore is considered internal and it cannot be relied upon.
Say I have a member variable that I can only allow to be an integer, but I also need it to be accessible outside of my class. I can supply traditional getters and setters, but Python has a better way. They are called properties, and there are two ways of implementing them. Each method makes use of the global
propertyfunction. The signature of this function is:property([fget[, fset[, fdel[, doc]]]]).The first method, in my opinion, clutters the namespace a bit. However, this is localized to a single class, and it is really no more clutter than a Java class with getters and setters.
class Foo(object): def __init__(self, x=0): self._x = x def _get_x(self): print 'get' return self._x def _set_x(self, new_x): print 'set' if type(new_x) is int: self._x = new_x else: raise AttributeError('x must be an int') def _del_x(self): print 'del' self._x = 0 x = property(_get_x, _set_x, _del_x)In this
Fooclass, the getter, setter, and deleter are denoted as internal using the leading underscore. However, a new member is added,x, that uses the supplied functions to perform the retrieval, updating, and deletion ofx.That method is fine, but I much prefer the second method. It just feels cleaner.
class Foo(object): def __init__(self, x=0): self._x = x @property def x(self): print 'get' return self._x @x.setter def x(self, new_x): print 'set' if type(new_x) is int: self._x = new_x else: raise AttributeError('x must be an int') @x.deleter def x(self): print 'del' self._x = 0This second method is identical to the outside world. Obviously, there is no
_get_xmethod any more, but the outside shouldn't be calling that anyway. In 2.6, thegetter,setter, anddeletermethods were added. They create a copy of the property with the decorated function. In the first example, if you want to create a getter and deleter, but no setter, you would need to typex = property(fget, None, fdel). In the second example, however, you would only use thedeletermethod of the existing property.Basically, stop writing getters and setters in Python. Please.