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
被调用而不是 Parent
的 x
setter。我怎样才能让它以 Pythonic 的方式使用 Parent
的 setter?
需要说明的是,当self.x = ...
出现在Parent
的方法中时,应该总是利用Parent
中的x
setter,当 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
。
我想从包含 属性 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
被调用而不是 Parent
的 x
setter。我怎样才能让它以 Pythonic 的方式使用 Parent
的 setter?
需要说明的是,当self.x = ...
出现在Parent
的方法中时,应该总是利用Parent
中的x
setter,当 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
。