Python:覆盖属性时的意外行为

Python: Unexpected behaviour when overriding properties

我想从包含 属性 x 的 class 继承,然后在子 class 中将此 属性 设置为只读通过覆盖 setter。如果父 class 中的 __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 setter Child 被调用而不是 Parentx setter。我怎样才能让它以 Pythonic 的方式使用 Parent 的 setter?

需要说明的是,当self.x = ...出现在Parent的方法中时,应该总是利用Parent中的xsetter,当 self.x = ... 出现在 Child 的方法中时,它应该始终使用 Child 中的 x setter,从而引发异常。

我设法通过换出

自己解决了问题
self.x = x

Parent.__init__

Parent.x.fset(self, x)

我也可以去掉

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

Child 中,如果不是 @x.setter,我使用 @Parent.x.setter