简体   繁体   English

Python:覆盖属性时发生意外行为

[英]Python: Unexpected behaviour when overriding properties

I would like to inherit from a class containing a property x , and then make this property read-only in the child class by overriding the setter. 我想从包含属性x的类继承,然后通过覆盖setter使此属性在子类中为只读。 This does not work if __init__ in the parent class uses the original setter. 如果父类中的__init__使用原始的setter,则此方法不起作用。 Consider the following code. 考虑以下代码。

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")

If I now try to instantiate Child , I get AttributeError: Illegal access to x because when the line self.x = x is called, the x setter of Child is called instead of the x setter of Parent . 如果我现在尝试实例Child ,我得到AttributeError: Illegal access to x ,因为当行self.x = x被调用时, x的二传手Child被调用,而不是x的二传手Parent How can I get it to use the setter of Parent in a Pythonic way? 如何以Python方式使用Parent的二传手?

To be clear, when self.x = ... appears in a method of Parent , it should always make use of the x setter in Parent , and when self.x = ... appears in a method of Child , it should always make use of the x setter in Child , and thus raise an exception. 需要明确的是,当self.x = ...出现在Parent方法中时,它应始终使用Parent中的x setter;当self.x = ...出现在Child方法中时,则应始终使用x setter利用Child中的x setter,从而引发异常。

I managed to solve the problem myself by swapping out 我设法通过换出解决了自己的问题

self.x = x

in Parent.__init__ with Parent.__init__

Parent.x.fset(self, x)

I can also get rid of 我也可以摆脱

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

in Child if instead of @x.setter , I use @Parent.x.setter . Child如果代替@x.setter ,我用@Parent.x.setter

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM