我对MRO和C3线性化算法感到困惑,无法解释以下代码,请您帮帮我吗?
class A(object):
def go(self):
print("A")
class B(A):
def go(self):
super(B, self).go()
print("B")
class C(A):
def go(self):
# super(C, self).go()
print("C")
class D(B, C):
def go(self):
super(D, self).go()
print("D")
d = D()
d.go()
pprint.pprint(D.__mro__)
The Result is:
C
B
D
(<class '__main__.D'>,
<class '__main__.B'>,
<class '__main__.C'>,
<class '__main__.A'>,
<class 'object'>)
另一个例子是:如果我取消注释C类中的super语句并注释B类中的super语句,结果将是“ B D”,没有C和A。为什么?! (我确实了解深度优先,从左到右的规则,但是……)
答案 0 :(得分:1)
super()
方法仅基于MRO查找下一个要调用的方法。
D.go()
调用B.go()
,然后调用C.go()
,后者打印C
,并返回到B.go()
,后者打印B
,最后返回到D.go()
,它显示D
如果您希望所有go()
方法都被调用,则必须取消注释super()
中的C.go()
调用。
您可以在Guido自己的blog
中找到有关MRO和super()
的更多信息
答案 1 :(得分:0)
来自Guido's blog:
MRO的计算被正式记录为使用像以前一样使用深度优先的从左到右遍历类。如果此搜索中有任何重复的类,则除了最后一次出现的所有类,都将从MRO列表中删除。
例如,如果有的话,
class A: pass
class B(A): pass
class C(A): pass
class D(B, C): pass
MRO会删除重复元素的最后一个实例,而不是简单的深度优先解析顺序D, B, A, C, A
,因此您将拥有D, B, C, A
。在您的情况下,您的班级C
不会将其称为super()
(因为您已将其注释掉)。因此,除非我弄错了,否则MRO会将呼叫推迟到A
之后C
,但是由于C
没有调用super()
,因此您永远不会看到{{1 }}称为:
A.go()