惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
The Blog of Author Tim Ferriss
I
InfoQ
H
Hackread – Cybersecurity News, Data Breaches, AI and More
aimingoo的专栏
aimingoo的专栏
小众软件
小众软件
有赞技术团队
有赞技术团队
J
Java Code Geeks
Apple Machine Learning Research
Apple Machine Learning Research
大猫的无限游戏
大猫的无限游戏
Engineering at Meta
Engineering at Meta
B
Blog RSS Feed
博客园_首页
Y
Y Combinator Blog
V
Visual Studio Blog
Google DeepMind News
Google DeepMind News
M
MIT News - Artificial intelligence
雷峰网
雷峰网
博客园 - 司徒正美
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
H
Help Net Security
P
Proofpoint News Feed
B
Blog
云风的 BLOG
云风的 BLOG
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报

博客园 - 箫笛

Tkinter - Entry 输入框组件 Tkinter - Button 组件 Tkinter - Label 组件 Tkinter - tk 变量 Tkinter - 事件与绑定 Tkinter - 几何管理器 Tkinter - 核心概念 Tkinter - 快速开始 Tkinter - 介绍 Python 编程 - 条件表达式 Python 编程 - 星号下划线参数释义 shell 编程 - shell 脚本的交互方式 Python insall - macOS 系统安装python的几种方式 Miniconda - Python 环境管理工具 Tkinter - Python GUI 开发 Python 编程 - 下划线命名的区别 Python 编程 - 元类编程 Python 编程 - 描述符协议 Python 编程 - 类型注解 Python 编程 - 生成器表达式 Python 编程 - 集合 Python 编程 - 装饰器 Python 编程 - 闭包 Python 编程 - 列表推导式 Python 编程 - 函数式编程 Python 编程 - lambda 函数 Python 编程 - 文件操作 Python 编程 - 输入与输出 Python 编程 - 面向对象编程 Python 编程 - 元组(tuple)
Python 编程 - 多重继承与MRO
箫笛 · 2026-07-03 · via 博客园 - 箫笛

Python 3 的多重继承通过 C3 线性化算法 来计算方法解析顺序(MRO),确保在复杂的继承体系下,方法调用是有序、可预测的。

🧠 什么是 MRO?

MRO 是一个线性列表,它定义了 Python 在继承体系中查找方法或属性的顺序。在单继承中,顺序很简单(从子类到父类);但在多重继承中,这个顺序就由 C3 算法 来决定了。

⚙️ C3 线性化算法核心

C3 算法的目标是生成一个满足所有继承规则的、单调的类顺序。其核心思想是合并(Merge)所有父类的线性化列表。

可以这样理解合并过程:

  1. 从第一个列表的头部(第一个元素)开始。
  2. 如果这个头部没有出现在其他列表的尾部(除第一个元素外的部分),就把它取出,放到结果列表中。
  3. 否则,跳过它,检查下一个列表的头部。
  4. 重复这个过程,直到所有类都被处理。

🔍 如何查看 MRO?

你可以直接通过类的 __mro__ 属性或 mro() 方法来查看其 MRO。

class A: pass
class B(A): pass
class C(A): pass
class D(B, C): pass

print(D.__mro__)
# 输出: (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)

这个结果就是 MRO 顺序。

💎 经典案例:菱形继承(钻石问题)

“钻石问题”是多继承的经典难题。假设有这样的继承关系:A 是顶层父类,BC 继承自 AD 同时继承 BC。这形成了一个菱形结构。

如果没有 MRO,当 D 调用一个在 A 中定义的方法时,会引发混乱。但 Python 的 C3 算法能完美解决这个问题。

class A:
    def method(self):
        print("A")

class B(A):
    def method(self):
        print("B")
        super().method()

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

class D(B, C):
    def method(self):
        print("D")
        super().method()

d = D()
d.method()

执行结果会是

D
B
C
A

为什么会这样?
让我们看看 D 的 MRO:D -> B -> C -> A -> object
因此,super() 的调用链会严格按照这个顺序执行,从而保证每个类的方法只被调用一次,且顺序清晰。

🚀 最佳实践与注意事项

  1. 善用 super():在多重继承中,应始终使用 super() 来调用父类方法。它遵循 MRO,能确保方法链正确执行,避免硬编码父类名带来的问题。
  2. super() 的协作式设计:所有参与多重继承的父类,其 __init__ 等方法都应调用 super(),并设计为可接受 *args, **kwargs,以保证参数能正确传递。
  3. 优先使用 Mixin:Mixin 是包含特定功能的小类。用多重继承来“组合”Mixin,是一种清晰、安全的设计模式。
  4. 保持父类职责单一:每个父类应只负责一个明确的功能,避免复杂的继承树。
  5. 必要时考虑组合:如果继承关系过于复杂,可以考虑使用“组合”(将一个类作为另一个类的属性)来替代继承。

⚠️ 常见陷阱

  • 方法名冲突:当多个父类有同名方法时,MRO 决定最终调用哪个。
  • super() 初始化顺序:在 __init__ 中,super() 的调用顺序由 MRO 决定,要确保这种顺序对你是合理的。
  • 复杂的 MRO 难以调试:继承层次过深或过宽时,MRO 可能变得难以理解。可通过 ClassName.__mro__ 来辅助调试。

总而言之,Python 3 的 MRO 和 C3 算法为多重继承提供了强大且可靠的支撑。理解其原理并遵循最佳实践,就能安全、有效地利用多重继承来构建灵活的代码。