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

推荐订阅源

Google DeepMind News
Google DeepMind News
人人都是产品经理
人人都是产品经理
S
Securelist
P
Proofpoint News Feed
H
Help Net Security
S
Schneier on Security
T
Tenable Blog
C
Cisco Blogs
S
Security @ Cisco Blogs
博客园 - 司徒正美
博客园 - 叶小钗
Cisco Talos Blog
Cisco Talos Blog
Google DeepMind News
Google DeepMind News
C
Cybersecurity and Infrastructure Security Agency CISA
Google Online Security Blog
Google Online Security Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Hacker News: Ask HN
Hacker News: Ask HN
NISL@THU
NISL@THU
云风的 BLOG
云风的 BLOG
V
Vulnerabilities – Threatpost
T
The Blog of Author Tim Ferriss
aimingoo的专栏
aimingoo的专栏
W
WeLiveSecurity
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Jina AI
Jina AI
腾讯CDC
WordPress大学
WordPress大学
Simon Willison's Weblog
Simon Willison's Weblog
Vercel News
Vercel News
小众软件
小众软件
N
Netflix TechBlog - Medium
有赞技术团队
有赞技术团队
AWS News Blog
AWS News Blog
雷峰网
雷峰网
Forbes - Security
Forbes - Security
The Hacker News
The Hacker News
博客园 - 聂微东
F
Full Disclosure
量子位
Scott Helme
Scott Helme
宝玉的分享
宝玉的分享
A
About on SuperTechFans
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Schneier on Security
Schneier on Security
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
K
Kaspersky official blog
AI
AI
SecWiki News
SecWiki News
Webroot Blog
Webroot Blog
Martin Fowler
Martin Fowler

博客园 - 箫笛

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 编程 - 字符串(str) Python 编程 - 字典(dict) Python 编程 - 列表(list) Python 编程 - 数据类型和数据结构 Python 编程 - 语句 Python 编程 - 函数 windows - WSL 的安装与使用 shell编程 - dialog 程序使用指南 FE Team - 如何做好前端代码审查 git 提交的撤销和恢复 React15 - redux-saga 如何在saga中实现轮询接口调用? React15 - React CSS Modules BEM命名实践 React15 - React 15 中 componentWillReceiveProps 为什么会多次调用, 同时componentDidUpdate 也会多次调用? React15 - React15类组件多次执行render方法的原因? React15 - React15应用中代码逻辑复用方案 React15 - React状态同步问题解决 React15 - React 15 中 React.pureComponent 的使用场景 React15 - React 15应用在页面渲染时会多次执行类组件的render 函数的原因 React15 - React 15 中能用 componetDidUpdate 代替 componentWillReceiveProps 吗? React15 - React 15 生命周期函数详解 React15 - 如何在React 15中实现自定义的事件订阅与发送(例如组件间通信) React15 - React15应用中的事件订阅和发送机制 React15 - CSS中的BEM规范 React15 - React CSS Modules BEM命名实践 React15 - 写sass 样式文件,嵌套的结构好,还是扁平的结构好? React15 - sass 中 @mixin 和 @extend 的区别是什么? React15 - React 15 应用 如何使用Css moudules 方式进行模块化开发 React15 - React15应用Sass使用指南 React15 - React 15 应用如何进行性能优化?
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 算法为多重继承提供了强大且可靠的支撑。理解其原理并遵循最佳实践,就能安全、有效地利用多重继承来构建灵活的代码。