Python @property继承的正确方式解释了如何调用父类的setter方法。
class Number:
def __init__(self):
self._value = None
@property
def value(self):
assert self._value is not None
return self._value
@value.setter
def value(self, new_value):
self._value = new_value
class Integer(Number):
@property
def value(self):
return super().value
@value.setter
def value(self, new_value):
_value = int(new_value)
super(Integer, type(self)).value.fset(self, _value) # <----- OK with using type(self)
# super(Integer, self).value.fset(self, _value) # <----- Assert error with self
i = Integer()
i.value = 1 # cause assertion error with "super(Integer, self)"
print(i.value)
问题
使用super(Integer, type(self)).value.fset(self, _value)
,i.value = 1
按预期调用了setter。
使用super(Integer, self).value.fset(self, _value)
,i.value = 1
调用了getter而不是setter,因此导致断言错误。
AssertionError Traceback (most recent call last)
<ipython-input-8-2c57a07c128d> in <module>
35
36 i = Integer()
---> 37 i.value = 1
38 print(i.value)
<ipython-input-8-2c57a07c128d> in value(self, new_value)
32 _value = int(new_value)
33 #super(Integer, type(self)).value.fset(self, _value)
---> 34 super(Integer, self).value.fset(self, _value)
35
36 i = Integer()
<ipython-input-8-2c57a07c128d> in value(self)
10 @property
11 def value(self):
---> 12 assert self._value is not None
13 return self._value
问题
请帮助理解为什么super(Integer, self).value.fset(self, _value)
调用fset
时会进入getter而不是setter。阅读文档和文章,我发现将对象self
传递给方法是访问绑定到实例本身的方法的正确方式,但它并没有起作用。
super([type[, object-or-type]])
object-or-type 确定要搜索的方法解析顺序。搜索从类型后面的类开始。
例如,如果 object-or-type 的MRO为D -> B -> C -> A -> object,并且 type 的值为B,则 super() 将搜索C -> A -> object。
对象或类型的mro列出了getattr()和super()使用的方法解析搜索顺序。该属性是动态的,当继承层次结构更新时可能会更改。
In Python 3, the super(Square, self) call is equivalent to the parameterless super() call. The first parameter refers to the subclass Square, while the second parameter refers to a Square object which, in this case, is self. You can call super() with other classes as well:
def surface_area(self): face_area = super(Square, self).area() return face_area * 6 def volume(self): face_area = super(Square, self).area() return face_area * self.length
What about the second parameter? Remember, this is an object that is an instance of the class used as the first parameter. For an example, isinstance(Cube, Square) must return True.
By including an instantiated object, super() returns a bound method: a method that is bound to the object, which gives the method the object’s context such as any instance attributes. If this parameter is not included, the method returned is just a function, unassociated with an object’s context.
@classmethod
等内容很重要,但对于属性来说,在类上的查找只会返回属性对象。 - user2357112