Search code examples
pythonpropertiesgetter-setter

property.setter and inheritance


I have two classes, BaseClass and Subclass (where Subclass is a subclass of BaseClass). In each of these classes, I have a property 'foo' which I'd like to be able to get and set. The way in which 'foo' is set is independent of the class - it's done the same way in both BaseClass and Subclass. However, the way in which we 'get' the property 'foo' is dependent on the class. I would thus like a way to define my 'setter' on BaseClass and have it inherit to Subclass in such a way that it's compatible with the class-dependent implementations of the 'getter' in both Subclass and BaseClass.

My first instinct was to use python @property and @property.setter. I quickly ran into issues:

class BaseClass(object):
    def __init__(self):
        self._foo = None

    @property
    def foo(self):
        print 'BaseClass'

    @foo.setter       
    def foo(self, val):
        self._foo = val


class Subclass(BaseClass):

    @property
    def foo(self):
        print 'Subclass'

My naive hope was that the foo.setter would be inherited into Subclass and that it would be compatible with the Subclass implementation of the foo property. However:

b = BaseClass()
s = Subclass()
b.foo
BaseClass
s.foo
Subclass
b.foo = 'BaseClass!'
s.foo = 'Subclass!'
Traceback (most recent call last):
 File "<input>", line 1, in <module>
AttributeError: can't set attribute

I believe what is happening here is that the '@foo.setter' is being bound to the BaseClass namespace at compile time, and thus is not available to Subclass (although I could be wrong on this point).

Can anyone tell me a neat way of achieving what I want here? It doesn't necessarily need to use python property builtin, but that would be nice.


Solution

  • You can use @BaseClass.foo.getter to create a copy of the property with a different getter:

    class Subclass(BaseClass):
        @BaseClass.foo.getter
        def foo(self):
            print('Subclass')
    

    See the property documentation for details.