32
class human(object):
    def __init__(self, name=''):
        self.name = name

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):
        self._name = value

class superhuman(human):
    @property
    def name(self):
        return 'super ' + name

s = superhuman('john')
print s.name

# Doesn't work :( "AttributeError: can't set attribute"
s.name = 'jack'
print s.name

我希望能够覆盖该属性,但能够使用超级父级的设置器,而不必覆盖子类中的设置器。

这可能吗?

4

1 回答 1

48

使用.getter原始属性的装饰器:

class superhuman(human):
    @human.name.getter
    def name(self):
        return 'super ' + self._name

请注意,您必须使用全名才能访问父类上的原始属性描述符。

示范:

>>> 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符对象只是一个对象,尽管它可以有多个与之关联的方法(getter、setter 和 deleter)。现有描述符提供的.getter,.setter和装饰器函数返回描述符本身的副本,并替换该特定方法。.deleterproperty

因此,在您的human基类中,您首先使用装饰器创建描述符@property,然后将该描述符替换为同时具有 getter 和 setter@name.setter语法的描述符。之所以有效,是因为 python 装饰器用相同的名称替换了原始装饰函数,它基本上执行name = name.setter(name). 请参阅@property 装饰器如何工作?有关这一切如何运作的详细信息。

在您的子类中,您只需使用该技巧创建描述符的新副本,只需替换 getter。

于 2013-04-03T11:30:21.273 回答