Python MRO 方法解析顺序详解
核心概念 MRO(Method Resolution Order)是 Python 多继承的方法解析顺序,C3 线性化算法决定查找路径。
1. 定义
MRO = Method Resolution Order,方法解析顺序。
当 Python 类存在多继承时,调用 obj.方法(),解释器按照一套固定顺序遍历父类,查找该方法,这个遍历的先后列表就是 MRO。
作用:
- 解决多继承下同名方法冲突;
- 规定
super()实际调用哪个父类; - Python3 统一使用 C3 线性化算法 计算 MRO。
2. 核心背景:Python2 vs Python3
- Python2.2 以前:深度优先、从左到右(DFS),存在菱形继承二义性问题,废弃;
- Python2.3 ~ Python2.7:同时支持旧DFS + 新式类C3;
- Python3 全部是新式类:所有类默认继承
object,统一强制使用 C3 线性化算法生成 MRO,无旧算法。 你日常写代码(Python3.6/3.8/3.10)全部遵循 C3 MRO。
3. 如何查看一个类的MRO
两种等价方式:
# 方式1:类.__mro__ 属性,返回元组
print(MyClass.__mro__)
# 方式2:内置函数 mro(),返回列表
print(MyClass.mro())
3.1. 简单单继承示例
class A:
def hello(self):
print("A")
class B(A):
pass
print(B.__mro__)
# (B, A, object)
执行顺序:先找自身B → 父类A → 顶层object。
4. 经典问题:菱形多继承(钻石继承)
object
↑
A
/ \
B C
\ /
D
4.1. 代码实现
class A:
def say(self):
print("A")
class B(A):
def say(self):
print("B")
class C(A):
def say(self):
print("C")
class D(B, C):
pass
print(D.__mro__)
# 输出:(D, B, C, A, object)
d = D()
d.say() # 输出 B
查找逻辑:
- 先查 D 自身无 say;
- 按继承顺序先找 B,找到方法,直接执行,不再往后走 C、A。
5. C3 线性化核心规则(MRO生成规则)
给定类 C(B1,B2,B3...),C3 合并规则:
- 先取当前类放在最前面;
- 依次合并每个父类的 MRO 列表;
- 遵循单调性 + 局部优先:
- 子类永远出现在父类前面;
- 父类继承书写顺序保持先后;
- 菱形结构公共父类只出现一次,放在所有子类最后;
- 无法满足规则时直接抛出异常
RecursionError,拒绝创建类。
5.1. 反例:非法继承,C3无法生成MRO
class X(Y): pass
class Y(X): pass
# 循环继承,创建直接报错
6. MRO 决定 super() 调用逻辑(最关键生产知识点)
很多人误区:super() 不是单纯调用直接父类,是沿着当前MRO列表的下一个类。
6.1. 示例演示
class A:
def fn(self):
print("A.fn")
class B(A):
def fn(self):
print("B.fn")
super().fn()
class C(A):
def fn(self):
print("C.fn")
super().fn()
class D(B, C):
def fn(self):
print("D.fn")
super().fn()
print(D.__mro__) # D, B, C, A, object
d = D()
d.fn()
输出:
D.fn
B.fn
C.fn
A.fn
执行链路解释:
- D.fn 中
super()→ MRO下一位 B; - B.fn 中
super()→ MRO下一位 C; - C.fn 中
super()→ MRO下一位 A; - A.fn 无 super,结束。
如果把 D 改为
class D(C,B),MRO 变成(D,C,B,A,object),执行顺序立刻变化。
super()的行为完全由 MRO 顺序控制,和代码继承书写顺序强绑定。
7. 生产开发中MRO的实际坑(框架高频踩坑)
7.1. 场景1:多继承框架重写同名方法(Operator/LLM Agent类多层继承)
如果你分层封装基类:
# 基础接口
class BaseAgent:
def run(self): ...
# 监控扩展
class MonitorAgent(BaseAgent):
def run(self):
# 监控逻辑
super().run()
# 自愈扩展
class RepairAgent(BaseAgent):
def run(self):
# 修复逻辑
super().run()
# 组合业务Agent
class GpuAgent(MonitorAgent, RepairAgent):
def run(self):
super().run()
MRO:GpuAgent → MonitorAgent → RepairAgent → BaseAgent → object执行顺序:MonitorAgent.run → RepairAgent.run → BaseAgent.run
调换继承顺序 GpuAgent(RepairAgent, MonitorAgent),执行流程完全反转。
7.2. 场景2:ABC抽象基类多继承冲突
多层抽象接口叠加,若多个父类拥有同名抽象方法,MRO会按顺序匹配第一个实现类。
7.3. 场景3:第三方框架类多继承报错
如 Kopf、Django、FastAPI 自定义类多重继承时,继承顺序写错触发C3循环冲突,启动直接崩溃。
8. 核心总结面试速记
- MRO 全称:Method Resolution Order,方法解析顺序;
- Python3 全部新式类,统一使用 C3线性化算法;
- 查看方式:
类.__mro__/mro(类); - 作用:多继承时查找方法的遍历顺序,同时决定
super()跳转位置; - C3规则:子类在前、保持继承书写顺序、公共父类唯一后置;
super()不是找字面父类,是取MRO列表当前类的下一个;- 循环继承、顺序冲突会直接抛出异常,无法创建类。
关联文档