Python:覆盖属性时出现意外行为

时间:2016-05-19 14:35:38

标签: python python-3.x inheritance properties getter-setter

我想从包含属性x的类继承,然后通过覆盖setter使该属性在子类中是只读的。如果父类中的__init__使用原始setter,则此方法无效。请考虑以下代码。

class Parent:
    def __init__(self, x=1):
        # I want the following line to use the setter defined in the Parent
        # class, even when __init__ is called from Child using super.
        self.x = x
        # Other initialization of Parent goes here.

    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, value):
        """Check that x is non-negative."""
        if value < 0:
            raise ValueError("x must be non-negative.")
        self._x = value


class Child(Parent):

    def __init__(self):
        super().__init__()  # Need this for initialization.

    @property
    def y(self):
        return self._y

    @y.setter
    def y(self, value):
        """x can only be written to implicitly by setting y."""
        self._y = value
        self._x = abs(value)

    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, value):
        raise AttributeError("Illegal access to x")

如果我现在尝试实例化Child,我会AttributeError: Illegal access to x,因为当调用行self.x = x时,会调用x Child的设置者x Parent的{​​{1}}。如何让它以Pythonic方式使用Parent的setter?

要明确的是,当self.x = ...方法出现Parent时,应该始终使用x中的Parent设置器,以及self.x = ...时} Child方法中出现,应该始终使用x中的Child setter,从而引发异常。

1 个答案:

答案 0 :(得分:1)

我设法通过交换

来解决问题
self.x = x
<{1>}中的

Parent.__init__

我也可以摆脱

Parent.x.fset(self, x)

@property def x(self): return self._x 中,如果不是Child,我会使用@x.setter