Python

Python MRO 方法解析顺序详解

·7 分钟阅读·2710 字

Python MRO 方法解析顺序详解 的详细笔记

📋 目录

Python MRO 方法解析顺序详解

核心概念 MRO(Method Resolution Order)是 Python 多继承的方法解析顺序,C3 线性化算法决定查找路径。

1. 定义

MRO = Method Resolution Order,方法解析顺序。

当 Python 类存在多继承时,调用 obj.方法(),解释器按照一套固定顺序遍历父类,查找该方法,这个遍历的先后列表就是 MRO。

作用:

  1. 解决多继承下同名方法冲突
  2. 规定 super() 实际调用哪个父类;
  3. Python3 统一使用 C3 线性化算法 计算 MRO。

2. 核心背景:Python2 vs Python3

  1. Python2.2 以前:深度优先、从左到右(DFS),存在菱形继承二义性问题,废弃;
  2. Python2.3 ~ Python2.7:同时支持旧DFS + 新式类C3;
  3. 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

查找逻辑:

  1. 先查 D 自身无 say;
  2. 按继承顺序先找 B,找到方法,直接执行,不再往后走 C、A。

5. C3 线性化核心规则(MRO生成规则)

给定类 C(B1,B2,B3...),C3 合并规则:

  1. 先取当前类放在最前面;
  2. 依次合并每个父类的 MRO 列表;
  3. 遵循单调性 + 局部优先
  • 子类永远出现在父类前面;
  • 父类继承书写顺序保持先后;
  • 菱形结构公共父类只出现一次,放在所有子类最后;
  1. 无法满足规则时直接抛出异常 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

执行链路解释:

  1. D.fn 中 super() → MRO下一位 B;
  2. B.fn 中 super() → MRO下一位 C;
  3. C.fn 中 super() → MRO下一位 A;
  4. 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. 核心总结面试速记

  1. MRO 全称:Method Resolution Order,方法解析顺序;
  2. Python3 全部新式类,统一使用 C3线性化算法
  3. 查看方式:类.__mro__ / mro(类)
  4. 作用:多继承时查找方法的遍历顺序,同时决定 super() 跳转位置;
  5. C3规则:子类在前、保持继承书写顺序、公共父类唯一后置;
  6. super() 不是找字面父类,是取MRO列表当前类的下一个;
  7. 循环继承、顺序冲突会直接抛出异常,无法创建类。

关联文档

Yanche Blog

记录云原生、Linux、数据库等技术领域的学习心得,以及日常生活的思考与感悟。

© 2026 Yanche Blog. All rights reserved.

Powered by Astro