关于python:为什么基类在这个多重继承中不起作用?

Why the base class doesn't work in this multiple inheritance?

我对解释以下代码的MRO和C3线性化算法感到困惑,请你帮我一下好吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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。为什么?!!!!!!!(我确实先了解深度,从左到右规则,但是……)


super()方法只是根据mro找到下一个要调用的方法。

D.go()调用B.go(),然后调用C.go(),打印C,返回B.go(),打印B,最后返回D.go(),打印D

如果希望调用所有go()方法,则必须取消对C.go()中的super()调用的注释。

你可以从guido自己的博客上找到更多关于mro和super()的信息。


从圭多的博客:

The computation of the MRO was officially documented as using a depth-first left-to-right traversal of the classes as before. If any class was duplicated in this search, all but the last occurrence would be deleted from the MRO list.

例如,如果你有:

1
2
3
4
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()的调用,所以您永远不会看到A.go()的调用:

1
D.go() --> B.go() (--> A.go() removed by MRO) --> C.go() (x> A.go() not called)