Python继承MRO机制疑问:为何不同多继承场景执行结果不同?
先明确两个场景的继承结构和MRO计算结果,再拆解执行逻辑:
场景1:共同父类分支的执行逻辑
继承链:Parent(Middle1, Middle2),Middle1(Origin1),Middle2(Origin1)
用C3线性化算法计算的Parent的MRO列表是:[Parent, Middle1, Middle2, Origin1, object]
结合你描述的执行顺序(Origin1→Middle2→Middle1→Parent),推测每个类的hello()实现是先调用super().hello(),再打印自身标识,示例代码如下:
class Origin1: def hello(self): super().hello() # 指向MRO中Origin1的下一个类object,无hello方法 print("Origin1.hello") class Middle1(Origin1): def hello(self): super().hello() # 指向MRO中Middle1的下一个类Middle2 print("Middle1.hello") class Middle2(Origin1): def hello(self): super().hello() # 指向MRO中Middle2的下一个类Origin1 print("Middle2.hello") class Parent(Middle1, Middle2): def hello(self): super().hello() # 指向MRO中Parent的下一个类Middle1 print("Parent.hello")
调用Parent().hello()的执行链严格遵循MRO顺序:Parent→Middle1→Middle2→Origin1,每个super()都会触发下一个类的hello(),所以所有类的方法都被执行。
场景2:独立分支被忽略的核心原因
当Middle2改为继承Origin2后,继承链变为:Parent(Middle1, Middle2),Middle1(Origin1),Middle2(Origin2)
此时Parent的MRO列表更新为:[Parent, Middle1, Origin1, Middle2, Origin2, object]
你观察到Middle2和Origin2的hello()被忽略,本质是执行链在Origin1处中断:
- Middle1的
hello()通过super()调用Origin1的hello() - 如果Origin1的
hello()没有调用super().hello()(或调用后因object无对应方法终止),那么MRO中Origin1之后的Middle2、Origin2就不会被触发,自然不会执行它们的hello()
关键结论
Python的super()不是简单调用“父类方法”,而是基于当前实例的MRO列表,找到当前类之后的第一个类的同名方法。只有当每个类的目标方法都主动调用super()时,才会沿着MRO完整遍历所有分支。场景2的差异完全由MRO顺序变化+执行链中断导致。
内容的提问来源于stack exchange,提问作者IAmVerySmart

