Real world example about how to use property feature in python?
I am interested in how to use @property
in Python. I've read the python docs and the example there, in my opinion, is just a toy code:
class C(object):
def __init__(self):
self._x = None
@property
def x(self):
"""I'm the 'x' property."""
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
I do not know what benefit(s) I can get from wrapping the _x
filled with the property decorator. Why not just implement as:
class C(object):
def __init__(self):
self.x = None
I think, the property feature might be useful in some situations. But when? Could someone please give me some real-world examples?
Solution 1:
Other examples would be validation/filtering of the set attributes (forcing them to be in bounds or acceptable) and lazy evaluation of complex or rapidly changing terms.
Complex calculation hidden behind an attribute:
class PDB_Calculator(object):
...
@property
def protein_folding_angle(self):
# number crunching, remote server calls, etc
# all results in an angle set in 'some_angle'
# It could also reference a cache, remote or otherwise,
# that holds the latest value for this angle
return some_angle
>>> f = PDB_Calculator()
>>> angle = f.protein_folding_angle
>>> angle
44.33276
Validation:
class Pedometer(object)
...
@property
def stride_length(self):
return self._stride_length
@stride_length.setter
def stride_length(self, value):
if value > 10:
raise ValueError("This pedometer is based on the human stride - a stride length above 10m is not supported")
else:
self._stride_length = value
Solution 2:
One simple use case will be to set a read only instance attribute , as you know leading a variable name with one underscore _x
in python usually mean it's private (internal use) but sometimes we want to be able to read the instance attribute and not to write it so we can use property
for this:
>>> class C(object):
def __init__(self, x):
self._x = x
@property
def x(self):
return self._x
>>> c = C(1)
>>> c.x
1
>>> c.x = 2
AttributeError Traceback (most recent call last)
AttributeError: can't set attribute
Solution 3:
Take a look at this article for a very practical use. In short, it explains how in Python you can usually ditch explicit getter/setter method, since if you come to need them at some stage you can use property
for a seamless implementation.
Solution 4:
One thing I've used it for is caching slow-to-look-up, but unchanging, values stored in a database. This generalises to any situation where your attributes require computation or some other long operation (eg. database check, network communication) which you only want to do on demand.
class Model(object):
def get_a(self):
if not hasattr(self, "_a"):
self._a = self.db.lookup("a")
return self._a
a = property(get_a)
This was in a web app where any given page view might only need one particular attribute of this kind, but the underlying objects themselves might have several such attributes - initialising them all on construction would be wasteful, and properties allow me to be flexible in which attributes are lazy and which aren't.