bigywater.tech
Python · 18

MRO 与 C3 线性化:多继承时 Python 如何决定方法顺序

构造一个菱形继承结构,验证MRO的计算顺序,交换父类声明顺序看MRO怎么变,再验证一个无法线性化的继承关系会被Python直接拒绝。

D→B→C→A
菱形继承的MRO顺序
声明顺序敏感
交换父类顺序MRO跟着整体翻转
TypeError兜底
无法线性化的继承会被直接拒绝

做的事:一个经典的菱形继承结构

B和C都继承自A,D同时继承B和C——想知道d.who()该调用谁的方法。

代码class A: def who(self): return "A" class B(A): def who(self): return "B" class C(A): def who(self): return "C" class D(B, C): pass

验证:MRO是[D, B, C, A, object]

D自己没定义who,按MRO顺序找第一个有who的类。

结果D.__mro__ 是: ['D', 'B', 'C', 'A', 'object'] d.who() 调用的是: 'B'

D的方法解析顺序是"D自己→B→C→A→object"——不是简单的"先左边全部深度优先"(那样会是D→B→A→C→A,A重复出现),C3线性化保证了:每个类只出现一次,而且子类永远排在父类前面,多个父类之间保持它们在class语句里声明的顺序(B在C前面)。

验证:交换继承顺序,MRO整体翻转

只是把B(C,B)里的顺序换一下。

代码与结果class E(C, B): pass E.__mro__ 是: ['E', 'C', 'B', 'A', 'object']

验证了class语句里父类的书写顺序是有意义的——D(B, C) 和 E(C, B) 除了父类声明顺序互换,结构完全一样,但MRO完全翻转了B和C的相对位置,导致找同名方法时优先级也反过来了。

验证:不是所有继承关系都能被线性化

故意构造一个C3算法无法给出一致顺序的继承关系。

代码与结果class X: pass class Y: pass class M1(X, Y): pass class M2(Y, X): pass -- 故意反过来声明 class Bad(M1, M2): -- 会失败 pass 报错: TypeError: Cannot create a consistent method resolution order (MRO) for bases X, Y
M1要求"X在Y前面",M2要求"Y在X前面",两个要求互相矛盾——C3算法没法同时满足这两个约束,Python选择直接拒绝创建这个类,在class Bad(M1, M2) 这一行就抛出TypeError,而不是给出一个"凑合能用但语义混乱"的顺序。这也是多继承设计里一个的护栏:继承关系本身自相矛盾时,Python不会悄悄给你一个不确定的行为,而是在类定义阶段就报错拦下来。

分步演示:MRO是怎么算出来的

每一步都是本文上面用Python 3.14跑出来的原始结果。

C3线性化保证每个类只出现一次且顺序一致
这一步新验证的继承结构

    本文用到的工具

    • 本机 Python 3.14.7
    • __mro__:查看C3线性化算出的方法解析顺序
    京ICP备2026067502号-1京公网安备11010502063487号