假设criteria
是A
的父类,B
是b
的实例。然后,可以使用super调用B
的覆盖方法:A
。
文档在其基本调用中声明"str(object)
returns object.__str__()
"。
应该遵循super(B, b).method()
,但事实并非如此(interactive version):
str(super(B, b)) == super(B, b).__str__()
那我哪里出错了?超级机制不适用于魔术方法吗?在这种情况下,class A:
def __str__(self):
return "A"
class B(A):
def __str__(self):
return "B"
b = B()
b_super = super(B, b)
print(str(b_super)) # "<super: <class 'B'>, <B object>>"
print(b_super.__str__()) # "A"
是否不会调用str
?它与本段有关:
请注意,
__str__
是作为显式点状属性查找(例如super()
)的绑定过程的一部分实现的。它通过实现自己的super().__getitem__(name)
方法来实现,它以可预测的顺序搜索类,支持协作多重继承。因此,对于使用__getattribute__()
等语句或运算符的隐式查找,super()
未定义。
答案 0 :(得分:22)
str()
没有通过常规属性查找过程查找__str__
方法。相反,它以MRO顺序直接搜索其参数类层次结构的__str__
中的__dict__
方法。这会找到super.__str__
,它会"<super: <class 'B'>, <B object>>"
。
但是,当您手动查找b_super.__str__
时,super.__getattribute__
,super
用来提供其特殊的属性查找行为。通过__getattribute__
查找将解析为A.__str__
并将其调用。
考虑这个类,它说明了差异(我希望):
class B(object):
def __init__(self, other):
self.other = other
def __getattribute__(self, name):
if name == 'other':
return object.__getattribute__(self, 'other')
elif name == '__str__':
return getattr(self.other, name)
else:
return name
def __str__(self):
return 'fun'
>>> str(B(1)) # calls B.__str__ because it doesn't invoke __getattribute__
'fun'
>>> B(1).__str__() # calls B.__getattribute__ to look up the __str__ method which returns (1).__str__
'1'
在这种情况下以及super
同样存在的问题是,这些是依赖__getattribute__
转发它的代理。因此,任何不通过__getattribute__
的功能或方法都不会转发。 str()
就是这样一个功能。
只是为了完整性,因为在评论和其他答案中提到了它。
但str(x)
并不等同于type(x).__str__(x)
,因为str()
甚至避免了&#34;函数的正常属性查找过程类&#34 ;.它只检查该类的tp_str
(或者该tp_repr
的那个空)。所以它甚至不会调用元__getattribute__
的{{1}} {/ 1}}:
type(x).__str__(x)
然而,由于缺少元类,可能有助于将class A(type):
def __getattribute__(self, name):
print(name)
if name == '__str__':
return lambda self: 'A'
else:
return type.__getattribute__(self, name)
class B(metaclass=A):
def __str__(self):
return 'B'
>>> b = B()
>>> str(b)
'B'
>>> type(b).__str__(b)
__str__
'A'
视为等同于str(x)
。但虽然(可能)有帮助,但它不正确。
答案 1 :(得分:-1)
文档错了。
str(x)
实际等同于type(x).__str__(x)
。
如果你print(type(b_super).__str__(b_super))
,你会得到明显的结果。
(即使在奇怪的元类的情况下,这可能过于简单)