Reputation: 72
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.
Upvotes: 0
Views: 851
Reputation: 131
There are some interesting things going on here. BaseClass.foo
is an object, and the lines
@foo.setter
def foo(self, val):
self._foo = val
return a modified copy of that object.
In the SubClass, you are redefining this object by recreating the property and so you will need to write a new setter or follow Aran-Fey’s answer.
I found a similar question that might also help with understanding this idea.
Upvotes: 1
Reputation: 43136
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.
Upvotes: 1