python - 多重继承调用顺序

标签 python python-3.x multiple-inheritance super

 A      B
| |   |   |
C D   E   F
| |   |   |
    G     H
      |
      I


user@ubuntu:~/Documents/Python/oop_python$ cat tt.py
class A:
    def call_me(self):
        print("A")

class C(A):
    def call_me(self):
        super().call_me()
        print("C")

class D(A):
    def call_me(self):
        super().call_me()
        print("D")

class B:
    def call_me(self):
        print("B")

class E(B):
    def call_me(self):
        super().call_me()
        print("E")

class F(B):
    def call_me(self):
        super().call_me()
        print("F")

class G(C, D, E):
    def call_me(self):
        super().call_me()
        print("G")

class H(F):
    def call_me(self):
        super().call_me()
        print("H")

class I(G, H):
    def call_me(self):
        super().call_me()
        print("I")


user@ubuntu:~/Documents/Python/oop_python$ python3.2 -i tt.py
>>> i = I()
>>> i.call_me()
A
D
C
G
I

问题> 为什么BEF不打印?

//            updated based on comments from delnan

user@ubuntu:~/Documents/Python/oop_python$ cat tt.py
class BaseClass():
    def call_me(self):
        print("BaseClass")
    pass

class A(BaseClass):
    def call_me(self):
        super().call_me()
        print("A")

class C(A):
    def call_me(self):
        super().call_me()
        print("C")

class D(A):
    def call_me(self):
        super().call_me()
        print("D")

class B(BaseClass):
    def call_me(self):
        super().call_me()
        print("B")

class E(B):
    def call_me(self):
        super().call_me()
        print("E")

class F(B):
    def call_me(self):
        super().call_me()
        print("F")

class G(C, D, E):
    def call_me(self):
        super().call_me()
        print("G")

class H(F):
    def call_me(self):
        super().call_me()
        print("H")

class I(G, H):
    def call_me(self):
        super().call_me()
        print("I")

user@ubuntu:~/Documents/Python/oop_python$ python3.2 -i tt.py
>>> i = I()
>>> i.call_me()
BaseClass
B
F
H
E
A
D
C
G
I

最佳答案

一个常见的误解是 super() 将调用所有 父类(super class)方法。它不会。它只会调用其中一个。哪一个是super()根据一些特定的规则自动计算出来的。有时它调用的不是真正的父类(super class),而是兄弟类。但是不能保证所有的类都会被调用,除非所有类都依次使用 super()。

在这种情况下,A 和 B 没有调用 super。如果你将它添加到 A,它实际上会调用“缺失”类,但如果你将它添加到 B,你会得到一个错误,因为在这种特殊情况下,B 最终将成为“最后一个”(或第一个,取决于你如何看待它)类。

如果要使用 super(),最好的解决方案是 A 和 B 有一个实现 call_me 但不调用 super() 的公共(public)基类。 (感谢 delnan 的建议)。

但是,如果您知道您的类层次结构,您可以直接调用父类(super class)方法而不是使用 super()。请注意,在上面的例子中,这并不意味着每个类都必须直接调用它的每个基类。因此,这在您作为程序员无法完全控制类层次结构的情况下没有用,例如,如果您编写库或混合类。然后你必须使用 super()。

关于python - 多重继承调用顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8779409/

相关文章:

python - Pyparsing - 从混合的 jascii/ascii 文本文件中解析 jascii 文本?

python-3.x - 如何使用 lambda 函数将 LambdaLR 调度程序保存在 pytorch 中?

python - 为什么Python的C3 MRO依赖于一个公共(public)基类?

python - 具有 attrs 的 PyTorch 模块无法获取参数列表

Ruby 和模块化 - 是否有任何干净简单的方法可以从类中排除包含的||扩展模块/混合?

c++ - 当基类不包含数据成员时是否仍然需要虚拟继承?

python - 如何使用Python中的socks模块下载网页?

python - 高密度图模糊的链接数据选择点

python - 修改函数中的变量没有结果

python - 带索引恢复的 QListView