超级混乱的python多重继承super()

super confusing python multiple inheritance super()

我在使用Python中的多重继承,遇到了一个我无法理解的交叉情况。

以下是继承布局:

1
2
3
4
5
6
    A       F
  /   \     |
 B     C    |  
  \    |   /
    \  |  /  
       D

大家都熟悉的ABCD钻石。加上一个额外的"F"班,我把它扔进去玩。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class A(object):
    def foo(self, call_from):
        print"foo from A, call from %s" % call_from
        super(A, self).foo("A")

class B(A):
    def foo(self, call_from):
        print"foo from B, call from %s" % call_from
        super(B, self).foo("B")

class C(A):
    def foo(self, call_from):
        print"foo from C, call from %s" % call_from
        super(C, self).foo("C")

class F(object):
    def foo(self, call_from):
        print"foo from F, call from %s" % call_from

class D(B, C, F):
    def foo(self):
        print"foo from D"
        super(D, self).foo("D")

输出:

1
2
3
4
5
6
7
>>> d = D()
>>> d.foo()
foo from D
foo from B, call from D
foo from C, call from B
foo from A, call from C
foo from F, call from A

方法分辨率顺序:

1
2
>>> D.__mro__
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class '__main__.F'>, <type 'object'>)
  • foo from C, call from B代替foo from C, call from D
  • 埃多克斯1〔2〕只是把我扔了……

似乎super()是按照方法解析顺序链接起来的,忽略了类之间的关系,但我不确定。

有人能告诉我正确的方向来理解这种行为吗?

请记住,我正在努力理解语言本身。不想解决实际问题。所以我没有这个的用例。但如果有人能指出一个用例,那就太好了:)

UPDATE:

To summarize - super() simply let you know what is next to call base on the mro. It is not necessary the parent. While mro built base on the inheritance hierarchy, mro itself is not the inheritance hierarchy.


super()的要点是遵循方法分解顺序。这就是为什么你告诉它你自己的类,而不是你的父类。程序员很难预测下一个调用哪个类,所以您可以让super()来处理它。

你已经接到了D打来的电话,那么你怎么能接到D打来的C呢?d.foo()只能调用另一个foo(),因为在那里只有一个函数调用。它将是一个线性调用链,因此类必须线性化,这就是方法解析顺序所做的。


有时我发现在父类上调用super很有用。前任。

1
2
3
4
5
6
7
class TmpClass0(object):
    def tmp_method(self):
        print 'TmpClass0 tmp_method'

class TmpClass1(TmpClass0):
    def tmp_method(self):
        print 'TmpClass1 tmp_method'

现在,我想从tmpclass2的实例中使用tmpclass0的tmp_方法。

1
2
3
class TmpClass2(TmpClass1):                                                                              
    def tmp_method(self):
        super(TmpClass1, self).tmp_method()

结果:

1
2
3
4
In [107]: tmp_class2 = TmpClass2()                                                                                  

In [108]: tmp_class2.tmp_method()                                                                                  
TmpClass0 tmp_method