__mro__是python中每个类自动生成的只读属性,全称method resolution order,返回一个tuple,首项为该类本身,末项为object,中间按c3线性化算法排列父类。

直接用 类名.__mro__ 就能拿到元组形式的解析顺序,但要注意它只反映当前类定义时的静态继承结构,不随实例状态变化。
什么是 __mro__?它返回什么
__mro__ 是 Python 为每个类自动生成的只读属性,全称 Method Resolution Order,表示该类在查找方法或属性时的搜索顺序。它的值是一个 tuple,首项是类本身,末项是 object,中间按 C3 线性化算法排列父类。
常见错误现象:有人误以为 __mro__ 会包含混入(mixin)类的运行时插入顺序,其实不会——它只由 class 语句定义时的继承列表决定。
-
class A: pass→A.__mro__是(<class>, <class>)</class></class> -
class B(A): pass→B.__mro__是(<class>, <class>, <class>)</class></class></class> - 多重继承下顺序受声明顺序和 C3 规则共同约束,不是简单左→右拼接
查看 __mro__ 的几种实操方式
最常用的是直接打印,但要注意对象实例没有 __mro__,必须作用于类。
- 正确:
print(MyClass.__mro__)或print(type(obj).__mro__) - 错误:
obj.__mro__会触发AttributeError - 想格式化输出可转成换行字符串:
"\n".join([cls.__name__ for cls in MyClass.__mro__]) - 调试时建议搭配
help(MyClass),它会在 “Method resolution order:” 下自动展示相同内容
为什么有时 __mro__ 和实际调用不符?
因为 __mro__ 只管“找得到找不到”,不管“找的是不是你想要的那个”。真正影响行为的是方法是否被覆盖、是否用了 super()、以及是否动态修改了类字典(如手动赋值 MyClass.method = ...)。
- 子类重写了父类方法,
__mro__不变,但调用走的是子类版本 -
super()的行为依赖__mro__,但它从调用位置的下一个类开始搜,不是从头开始 - 如果用了
__getattr__或描述符,属性可能根本没进__mro__查找流程 - 动态添加父类(如修改
__bases__)后,__mro__不会自动更新,需手动触发class.__mro__重新计算(Python 不允许直接改__mro__)
真正容易被忽略的是:C3 算法对继承链有强约束,一旦出现无法线性化的组合(比如两个父类各自继承了同一个祖父类但顺序相反),Python 在类定义时就会报 TypeError: Cannot create a consistent method resolution order (MRO) —— 这时候看 __mro__ 已经没机会了。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











