Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do properties support inheritance?

In my code class A has a property, but class B doesn't inherit it. Does @property support inheritance? Or is it my fault?

class A(object):

    def __init__(self):
        self._x = 100

    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, v):
        self._x = v


class B(A):

    @x.setter
    def x(self, v):
        self._x = v

The error message is as below:

Traceback (most recent call last):
  File "test.py", line 9, in <module>
    class B(A):
  File "test.py", line 10, in B
    @x.setter
NameError: name 'x' is not defined
like image 333
Ryan Avatar asked Jan 06 '23 18:01

Ryan


1 Answers

The NameError is because x isn't in the global scope; it's defined within A's class namespace, so you need to access it there explicitly by using A.x. This is a pretty common mistake, see e.g. python subclass access to class variable of parent.

With properties, though, it can get slightly more complex. If you add a new setter in B, then there is no problem using A.x.setter as shown in Dean's answer. However, if you override an existing setter, you will also alter A's behaviour in doing so. I doubt this is the behaviour that you want.

Instead, in this case, you need to create a new property in the subclass with A's getter and a new setter. I think that this is this easiest way to achieve that, with minimal repetition:

class B(A):

    x = property(A.x.__get__)  # new property with same getter

    @x.setter  # new setter on new property
    def x(self, v):
        ...

Note the use of property without the @ syntactic sugar, as I'm not using it to decorate a new method. If you want to access A's setter from B's setter, you can do so with super().x.__set__(whatever).

like image 168
jonrsharpe Avatar answered Jan 12 '23 00:01

jonrsharpe