def __init__(self, name=''):
self.name = name
def name(self, value):
self._name = value
return 'super ' + name
s = superhuman('john')
# Doesn't work :( "AttributeError: can't set attribute"
s.name = 'jack'
Use just the
.getter decorator of the original property:
class superhuman(human): @human.name.getter def name(self): return 'super ' + self._name
Note that you have to use the full name to reach the original property descriptor on the parent class.
>>> class superhuman(human): ... @human.name.getter ... def name(self): ... return 'super ' + self._name ... >>> s = superhuman('john') >>> print s.name super john >>> s.name = 'jack' >>> print s.name super jack
property descriptor object is just one object, even though it can have multiple methods associated with it (the getter, setter and deleter). The
.deleter decorator functions provided by an existing
property descriptor return a copy of the descriptor itself, with that one specific method replaced.
So in your
human base class what happens is that you first create the descriptor with the
@property decorator, then replace that descriptor with one that has both a getter and a setter with the
@name.setter syntax. That works because python decorators replace the original decorated function with the same name, it basically executes
name = name.setter(name). See How does the @property decorator work? for the details on how that all works.
In your subclass you simply use that trick to create a new copy of the descriptor with just the getter replaced.