A few days ago I was asked by a collegaue what the point of properties in Python is. After all, writing properties is as much text as writing getters and setters, and they don’t really add any functionality except from not having to write ’()’ on access.
On the surface, this argument holds as we can see by comparing a simple class implemented with getters and setters, and with properties.
Implemented with getters and setters
>>> class GetSet(object): ... def __init__(self): ... self.x = 0 ... def set_x(self, x): ... self.x = x ... def get_x(self): ... return self.x ... >>> getset = GetSet() >>> getset.set_x(3) >>> getset.get_x() 3
And implemented with properties
>>> class Props(object): ... def __init__(self): ... self._x = 0 ... @property ... def x(self): ... return self._x ... @x.setter ... def x(self, x): ... self._x = x ... >>> props = Props() >>> props.x = 5 >>> props.x 5
In fact, we’ve gone from 196 to 208 chars in this simple use case – so why would we use properties at all?
The answer is, that in this use case we would not. In fact, we would write thus:
>>> class MyClass(object): ... def __init__(self): ... self.x = 0 ... >>> my = MyClass() >>> my.x = 4 >>> my.x 4
’But!’, I can hear you scream, ’there’s no encapsulation!’. What will we do if we need to control access to x, make it read-only or do something else to it? Won’t we have to refactor everything to the getters and setters that we avoided?
No – we just switch to the property version, add whatever we want, and have not changed the interface one iota! The great thing about properties is not that they replace getters and setters, its that you don’t have to write them to future-proof your code. You can start out by writing the simplest implementation imaginable, and if you later need to change the implementation you can still do so without changing the interface. Neat, huh?