property.setter 和继承

property.setter and inheritance

我有两个 class,BaseClass 和 Subclass(其中 Subclass 是 BaseClass 的子class)。在这些 classes 中的每一个中,我都有一个 属性 'foo',我希望能够获取和设置它。 'foo' 的设置方式独立于 class - 在 BaseClass 和 Subclass 中的设置方式相同。但是,我们'get' 属性 'foo' 的方式取决于class。因此,我想要一种在 BaseClass 上定义我的 'setter' 并让它以与 [=28= 的 class 相关实现兼容的方式继承到 Subclass 的方法] 在 Subclass 和 BaseClass.

我的第一直觉是使用 python @属性 和 @property.setter。我很快 运行 进入问题:

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'

我天真的希望 foo.setter 会继承到 Subclass 中,并且它会与 foo 属性 的 Subclass 实现兼容。然而:

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

我相信这里发生的是 '@foo.setter' 在编译时被绑定到 BaseClass 命名空间,因此对 Subclass 不可用(尽管我可以在这一点上是错误的)。

谁能告诉我实现我想要的东西的巧妙方法?它不一定需要使用 python 属性 内置,但那会很好。

这里发生了一些有趣的事情。 BaseClass.foo 是一个对象,行

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

return 该对象的修改副本。

在子类中,您正在通过重新创建 属性 来重新定义此对象,因此您需要编写一个新的 setter 或遵循 Aran-Fey 的回答。

我发现了一个 similar question 可能也有助于理解这个想法。

您可以使用 @BaseClass.foo.getter 创建具有不同 getter 的 属性 的副本:

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

详情见the property documentation