Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python - multiple @property statements in class definition?

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?

like image 710
Alan S Avatar asked Feb 20 '14 20:02

Alan S


3 Answers

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.

like image 163
Martijn Pieters Avatar answered Oct 24 '22 03:10

Martijn Pieters


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

like image 27
Luis Masuelli Avatar answered Oct 24 '22 04:10

Luis Masuelli


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 !

like image 22
smarie Avatar answered Oct 24 '22 04:10

smarie