在Python中重写继承属性的getter和setter

45 投票
2 回答
30836 浏览
提问于 2025-04-16 01:51

我现在在一些类里使用 @property 装饰器来实现“获取器和设置器”。我希望能够在子类中继承这些 @property 方法。

我有一些 Python 代码(具体来说,我是在 py3k 中工作),大概是这样的:

class A:
    @property
    def attr(self):
        try:
            return self._attr
        except AttributeError:
            return ''

class B(A):
    @property
    def attr(self):
        return A.attr   # The bit that doesn't work.

    @attr.setter
    def attr(self, value):
        self._attr = value

if __name__ == '__main__':
    b = B()
    print('Before set:', repr(b.attr))
    b.attr = 'abc'
    print(' After set:', repr(b.attr))

我在注释中标出了不工作的部分。我想要基类的属性获取器被返回。A.attr 返回一个属性对象(这可能正是我需要的!)。

编辑:
在收到 Ned 的回答后,我想到了一个我认为更优雅的解决方案。

class A:
    @property
    def attr(self):
        try:
            return self._attr
        except AttributeError:
            return ''

class B(A):        
    @A.attr.setter
    def attr(self, value):
        self._attr = value

if __name__ == '__main__':
    b = B()
    print('Before set:', repr(b.attr))
    b.attr = 'abc'
    print(' After set:', repr(b.attr))

.setter 装饰器需要一个属性对象,我们可以通过 @A.attr 来获取。这意味着我们在子类中不需要重新声明这个属性。

(这就是在一天结束时解决问题和在一天开始时解决问题的区别!)

2 个回答

43

在Python 2中,要重写一个设置器(setter),我这样做:

class A(object):
    def __init__(self):
        self._attr = None

    @property
    def attr(self):
        return self._attr

    @attr.setter
    def attr(self, value):
        self._attr = value


class B(A):
    @A.attr.setter
    def attr(self, value):
        # Do some crazy stuff with `value`
        value = value[0:3]
        A.attr.fset(self, value)

要理解A.attr.fset是从哪里来的,可以查看property类的文档: https://docs.python.org/2/library/functions.html#property

9

我觉得你想要的是:

class B(A):
    @property
    def attr(self):
        return super(B, self).attr

你提到想要返回父类的获取器(getter),但其实你需要调用这个获取器,而不是直接返回它。

撰写回答