Getting up to speed on learning classes. I have been reading that the constructor (def init in Python) should only set assigned variables, that calculated instance attributes should be set via a property. Also, that using @property is preferred to a Java-style getter/setter.
OK, but every example I have ever seen on this sets only one property. Let's say I have an object with three complicated attributes that need to be calculated, queried etc. How do you represent multiple @property getters, setters, deleters? Here is an example from another post:
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
So if I had three instance variables that were calculated values based on some other attributes, would it look like this
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
@property
def y(self):
"""I'm the 'y' property."""
return self._y
@y.setter
def y(self, value):
self._y = value
@y.deleter
def y(self):
del self._y
@property
def z(self):
"""I'm the 'z' property."""
return self._z
@z.setter
def z(self, value):
self._z = value
@z.deleter
def z(self):
del self._z
Or is that fact that I only ever see one @property
statement mean that having a class with more than one @property
is a bad idea?
No, you can use multiple @property
decorators to your heart's content. There is no limit here, other than that of example writers imaginations, apparently.
The Python standard library is full of @property
use if you want examples:
numbers
defines ABCs for the numbers classes in Python.
tempfile
implements temporary file objects
threading
provding higher-level thread support
urlparse
for handling URLs and query strings.
etc.
You had it spot on; multiple properties would look exactly like what you posted.
it's not a bad idea. it's a regular property pattern.
another pattern is doing like:
class A(object):
def _get_a(self):
return self._a
def _set_a(self, v)
self._a = v
def _del_a(self)
del self._a
a = property(_get_a, _set_a, _del_a)
the result is the same that in the first example, and you can use it as much as you wish. initializing self._a in the constructor is a good idea, since otherwise, accesing it BEFORE by calling self.a would raise AttributeError
To bounce on another answer,
there is no shortcut to the somewhat ugly looking pattern
Not in python stdlib indeed, but there is now a library named pyfields
to do this in a more concise way, without sacrificing speed when you do not need validators not converters.
from pyfields import field, init_fields
class C(object):
x = field(default=None, doc="the optional 'x' property")
y = field(doc="the mandatory 'y' property")
z = field(doc="the mandatory 'z' property")
@init_fields
def __init__(self):
pass
c = C(y=1, z=2)
print(vars(c))
yields
{'z': 2, 'y': 1, 'x': None}
I'm the author of this lib, I wrote it because none of the existing alternatives were satisfying to me.
See documentation for details - Do not hesitate to provide feedback !
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With