Python 进阶
Python 协程实现原理
dict 和 set 实现原理
Python 线程安全
Python 抽象语法树(AST)
Python 日志输出
Python 扩展入门(一)
Python 程序执行原理
Python 垃圾回收
yield 生成器工作原理
django 源码分析:请求处理过程
dict 设计与实现
Python 性能分析原理
PyCodeObject
Python 弱引用
Python 性能分析原理(二)
Python 源码分析(一)
Python Annotated
Python 依赖注入
检查工具
Python MRO
Python 标记清除
PyFrameObject
Python 动态创建类
python freelist
python代码编译成pyc
Python mmap 内存映射文件
Python值得学习的内容
async Future 对象
asyncio loop的实现
asyncio.sleep 的实现
asyncio 原理
Python 代码加密
Python Token类型
Python 扩展入门(二)
Python 性能优化
本文档使用 MrDoc 发布
-
+
首页
Python MRO
### 概述 在 Python 中,MRO(Method Resolution Order,方法解析顺序)是指类继承体系中,Python 如何确定在调用方法时的解析顺序。MRO 决定了在多继承环境下,Python 如何寻找方法或属性,即它会根据一定规则从父类中查找方法或属性,避免重复继承带来的歧义。 ### MRO介绍 在 Python 中,类可通过多继承(即从多个父类继承)来获得不同父类的功能。为了避免由于多继承带来的冲突和不确定性,Python 使用了 MRO 来确定方法调用的顺序。 从 Python 2.3 [1]开始,Python 使用 C3 线性化算法 来决定类的 MRO。Python 的继承系统遵循该算法,这使得继承路径清晰且无二义性。 ### MRO计算步骤 1. MRO计算步骤 >s `MRO计算步骤` > - 从当前类开始,将当前类添加到MRO列表的末尾; > - 从左到右遍历当前类的基类列表; > - 对于每个基类,如果它还没有被添加到MRO列表中,将其添加到MRO列表的末尾,并递归地重复步骤2; > - 如果基类列表为空,则结束; 2. 查看类的MRO 在 Python 中,可通过 `__mro__` 属性或内置的 `mro()` 方法来查看类的 MRO。如下所示: ``` class A: def foo(self): print("A") class B(A): def foo(self): print("B") class C(A): def foo(self): print("C") class D(B, C): pass # 查看类 D 的 MRO print(D.__mro__) # 或者 print(D.mro()) ``` 输出结果显示 D 类的 MRO 顺序: ``` (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>) ``` 这个 MRO 表示 Python 将首先在 D 类中查找方法,如果没有找到,再去 B 类,然后是 C 类,接着是 A 类,最后是 object 类。 ### C3线性化算法 1. 算法特性 - 单调性:MRO列表在继承过程中是单调的,这意味着一旦一个类被添加到MRO中,它就不会再被添加到后面的类中。 - 非循环性:MRO列表不会包含任何循环。 - 保持子类顺序:如果一个类B继承自类A和类C,那么A应该在C之前出现在MRO中。 2. 简单示例 假设有以下类继承关系,如下所示: ``` class A: pass class B(A): pass class C(A): pass class D(B, C): pass ``` 3. MRO 计算过程 - D 类的直接父类是 B 和 C,因此 MRO 将从这两个类开始。为了保证类 B 在类 C 之前解析(因为 B 在 D 类的声明中出现在前面),MRO 按顺序选择 B 和 C。 - 然后,MRO 会解析 B 和 C 各自的父类 A,确保 A 只出现一次,且在 B 和 C 之后。 - 最后,所有类都继承自 object 类。 这样最终 MRO 为 [D, B, C, A, object]。 >w 注意: > 在不同情况下,c3 算法可能表现为广度优先,也可能表现为深度优先 4. C3 算法算法表现为广度优先的情况 ``` # C3-广度优先(D -> B -> C -> A) class A: var = 'A var' class B(A): pass class C(A): var = 'C var' class D(B, C): pass if __name__ == '__main__': # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>] print(D.mro()) # C var print(D.var) ``` 5. C3 算法表现为深度优先的情况 ``` # C3-深度优先(D -> B -> A -> C) class A: var = 'A var' class B(A): pass class C: var = 'C var' class D(B, C): pass if __name__ == '__main__': # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>] print(D.mro()) # A var print(D.var) ``` 6. super()函数与MRO >s 在多继承中,super() 函数使用 MRO 来决定调用顺序。 `super()` 会沿着 MRO 顺序依次调用下一个类的方法。如下所示: ``` class A: def foo(self): print("A") class B(A): def foo(self): super().foo() print("B") class C(A): def foo(self): super().foo() print("C") class D(B, C): def foo(self): super().foo() print("D") d = D() d.foo() ``` 这里super() 将沿着 D 类的 MRO 顺序调用 foo() 方法。输出结果为: ``` A C B D ``` 这表明 Python 沿着 MRO 的顺序依次调用了 `A -> C -> B -> D`。简单理解,foo()方法执行顺序与D类的MRO顺序相反。 ### MRO解决的问题 1. 避免菱形继承问题 在多重继承中,如果不同的父类继承自同一个祖先类,MRO 确保这个祖先类的方法只会调用一次。 2. 保证方法查找的有序性 MRO 保证了在多继承中有明确的解析顺序,不会出现不确定性或冲突。 ### 总结 MRO是Python中一个复杂但重要的概念,它通过C3线性化算法计算出一个类的所有基类的有序列表,这个列表决定了方法或属性在多重继承中的查找顺序。理解MRO有助于编写更清晰、更健壮的Python代码。 ### 参考 > [Python中的方法解析顺序(MRO)](https://z0yrmerhgi8.feishu.cn/wiki/EXUjwJqItiFdHXkkLMccOXufnPh) > [小白都能理解的Python多继承](https://zhuanlan.zhihu.com/p/159967682) > [Python多重继承问题-MRO和C3算法](https://zhuanlan.zhihu.com/p/151856162) > [C3 算法:Python 多继承的内部原理](https://lotabout.me/2020/C3-Algorithm/)
gaojian
2025年6月13日 14:46
分享文档
收藏文档
上一篇
下一篇
微信扫一扫
复制链接
手机扫一扫进行分享
复制链接
关于 MrDoc
觅思文档MrDoc
是
州的先生
开发并开源的在线文档系统,其适合作为个人和小型团队的云笔记、文档和知识库管理工具。
如果觅思文档给你或你的团队带来了帮助,欢迎对作者进行一些打赏捐助,这将有力支持作者持续投入精力更新和维护觅思文档,感谢你的捐助!
>>>捐助鸣谢列表
微信
支付宝
QQ
PayPal
Markdown文件
分享
链接
类型
密码
更新密码