Python中类的mro与继承关系详解
前言MRO 是 Method Resolution Order 的缩写中文常译作方法解析顺序。它回答一个问题当一个实例调用某个方法时Python 按什么顺序去各个类里找它单继承时这个问题看起来没什么可讲的——子类没有就往上找父类一条直线。但 Python 支持多重继承一个类可能有两条甚至更多路径通向同一个祖先这时往上找就不再是一条直线了。文档把这种结构称为菱形关系diamond relationship因为所有类最终都继承object任何多重继承都天然构成菱形。Python 的解法是C3 线性化把一个类及其所有祖先排成一个不重复的线性序列。围绕它常见的误解有两个以为多重继承的方法是深度优先、从左到右地全跑一遍。实际每个类只会被选中一次super()靠这个线性序列接力。以为 MRO 只看继承列表的书写顺序。实际上它还受每个基类自身的继承结构影响光看class D(B, C)猜不准。本文讲 C3 的规则、怎么查看 MRO以及它和super()的关系。一、MRO 要解决什么假设有这样一组类A/ \B C\ /DB和C都继承AD又同时继承B和C。如果按深度优先、从左到右去找方法先找D再找B再找B的父类A——可这时C还没被找过而A已经被找了两遍。谁先谁后、会不会重复就说不清了。文档对 Python 采用的算法的描述是它保持每个类声明时的从左到右顺序、每个父类只被访问一次、并且是单调的即一个类被继承后不会打乱已有父类的优先级。这套规则让多重继承的行为变得可预测。二、C3 线性化的结果长什么样先看最经典的菱形# 适用于 Python 3.8class A:passclass B(A):passclass C(A):passclass D(B, C):passprint([cls.__name__ for cls in D.__mro__])# [D, B, C, A, object]顺序是D → B → C → A → object。注意两点B和C谁在前面由class D(B, C)的书写顺序决定A排在两者之后而不是紧跟B——这正是线性化避免重复访问的手段。下表用查找某个方法时依次去哪些类找的角度列出几种继承结构的 MRO类定义MROclass B(A)B, A, objectclass C(A)C, A, objectclass D(B, C)D, B, C, A, objectclass E(C, B)E, C, B, A, objectclass F(D, E)冲突抛TypeError最后一行值得说明D要求B在C前E要求C在B前两者矛盾C3 无法给出一个一致序列于是 Python 直接报TypeError: Cannot create a consistent method resolution order (MRO)。三、查看 MRO__mro__ 与 mro()每个类都有__mro__属性它是一个元组列出方法解析时会依次检查的类# 适用于 Python 3.8class A:passclass B(A):passprint(B.__mro__)# (class __main__.B, class __main__.A, class object)类上还有mro()方法返回的是列表形式。文档说明mro()可以被元类重写用于自定义 MRO它在类创建时被调用结果存进__mro__。# 适用于 Python 3.8print(B.mro())# [class __main__.B, class __main__.A, class object]排查继承问题时第一件事就是打印类名.__mro__——它比任何推测都可靠。另外__bases__给出的是直接基类的元组__mro__才是完整链条两者别混用。四、MRO 与 super() 的配合这是 MRO 最实际的用途。super()返回一个代理对象从 MRO 中当前类之后的位置继续搜索。文档举的例子是如果__mro__是D - B - C - A - object而type是B那么super()会在C - A - object里找。# 适用于 Python 3.8class Base:def handle(self):return [Base]class AuthMixin:def handle(self):return [Auth] super().handle()class LogMixin:def handle(self):return [Log] super().handle()class API(AuthMixin, LogMixin, Base):passprint([c.__name__ for c in API.__mro__])# [API, AuthMixin, LogMixin, Base, object]print(API().handle())# [Auth, Log, Base]AuthMixin.handle里的super()跳到了LogMixin——这是它的MRO 后继不是它的父类AuthMixin的父类其实是object。这里就体现出 MRO 与super()是一体的不知道 MRO就预测不出super()会跳到哪。如果某个环节忘了写super()它后面的所有实现都会被静默跳过程序不报错# 适用于 Python 3.8class LogMixin:def handle(self):return [Log] # 没调 super()Base 永远轮不到五、MRO 冲突怎么排查出现Cannot create a consistent method resolution order (MRO)时说明继承结构本身矛盾典型是把祖先排在了后代后面# 适用于 Python 3.8class A:passclass B(A):pass# class C(A, B): # TypeError: Cannot create a consistent MRO# passB已经是A的子类class C(A, B)却要求A排在B前面这与A必须在B之后相矛盾。排查步骤建议固定成三条写出每个涉及类的__bases__画成图从上到下检查有没有祖先排在后代之后的写法试着删掉某个基类看是否是因为它把两条无关的链条强行合并导致矛盾。常见坑点1. 以为super()指的就是直接父类❌ 在多重继承里断言AuthMixin.handle里的super()会调到自己的父类。✅ 它调到的是当前实例的 MRO 中当前类之后的下一个类要打印__mro__才能确定。2. 用深度优先预测顺序❌ 以为D(B, C)会先把B的整条祖先链找完再找C。✅ C3 的输出是D, B, C, A, object——A被排到C之后。3. 在嵌套函数 / 生成器表达式里用零参super()❌ 以为super()在哪都能自动认出当前类和self于是在方法内部又套一层函数时照写super()。✅ 零参super()靠编译器在外围方法里填入当前类与第一个参数嵌套函数里不成立生成器表达式也会隐式生成嵌套函数这种场合要写显式两参形式super(当前类, self)。4. 以为继承列表相同MRO 就相同❌ 看到两个类都写成(X, Y)就断定它们的解析顺序完全一致。✅ 顺序还取决于X、Y各自继承了谁上游结构一变下游顺序可能跟着变必须打印__mro__才算数。5. 用__bases__当完整链条❌ 打印D.__bases__只看到(B, C)就以为这是全部顺序。✅__bases__是直接基类完整顺序看__mro__。6. MRO 冲突时反复调换顺序试错❌ 遇到TypeError就把继承列表换来换去直到不报错。✅ 冲突说明结构矛盾祖先排在了后代之后需要重新设计层次。7. 在子类里给__mro__赋值❌ 运行中直接SomeClass.__mro__ ...想强行改顺序。✅__mro__是只读的要自定义解析顺序只能在元类里重写mro()且在类创建前生效。8. 忘了每个类的 MRO 末尾都有object❌ 统计链长时漏算object或以为重写object的方法能救场。✅ 所有类的 MRO 都以object结尾多重继承里它只出现一次这也是任意多重继承都是菱形的原因。总结概念说明MRO属性/方法查找的顺序算法C3 线性化保持从左到右、每个类一次、单调查看方式类.__mro__元组、类.mro()列表super()从 MRO 中当前类之后继续搜索冲突表现TypeError: Cannot create a consistent MROMRO 不是一条只供阅读的规则它是super()行为的依据。想预测一段多重继承代码会调到哪个方法唯一可靠的办法就是打印__mro__再顺着序列看每个类的实现是不是都调了super()。把这两步养成习惯多重继承就不再是黑箱。

相关新闻

DSC曲线分析全指南:从读图到热分析参数提取

DSC曲线分析全指南:从读图到热分析参数提取

1. DSC曲线分析到底在分析什么第一次拿到DSC曲线的人,十有八九会盯着那条忽上忽下的线发懵——横坐标是温度,纵坐标是热流率,曲线上冒出一个向下的峰,或者鼓起一个向上的包,然后呢?然后该看什么&#xff1f…

2026/10/9 23:58:37 阅读更多 →
IIS7导出包真相:配置继承、内核参数与默认安全陷阱

IIS7导出包真相:配置继承、内核参数与默认安全陷阱

1. 这个“导出包”到底导出了什么?——IIS7默认配置的真相与误读很多人看到“IIS7默认配置及故障排除导出包”这个标题,第一反应是:这不就是个备份脚本或一键恢复工具吗?点几下鼠标,导出一个zip包,出问题了…

2026/10/9 23:58:37 阅读更多 →
U盘容量变小真相:GiB/GB换算、GPT分区与文件系统开销解析

U盘容量变小真相:GiB/GB换算、GPT分区与文件系统开销解析

1. 问题不是U盘“缩水”,而是分区表和文件系统在“装睡”你刚把一张崭新的64GB U盘插进电脑,用Linux的fdisk -l或lsblk一查,发现它只显示58.2GB;更糟的是,格式化完再看,df -h里可用空间只剩52GB出头——心里…

2026/10/9 23:57:37 阅读更多 →

最新新闻

糖尿病视网膜病变AI诊断:从Jupyter原型到临床闭环的工程化实践

糖尿病视网膜病变AI诊断:从Jupyter原型到临床闭环的工程化实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 2:30:00 阅读更多 →
Spring Boot + Vue 设备管理系统全栈开发实战与选型指南

Spring Boot + Vue 设备管理系统全栈开发实战与选型指南

很早就想聊聊设备管理这类系统的开发套路,正好有个朋友最近在做一个“公司企业设备信息管理系统”,技术栈写的是 nodejsvue 基于 springboot 这串组合。乍一看有点乱,但拆开来看其实就是两个经典分支:后端要么走 Node.js 那套&…

2026/10/10 2:30:00 阅读更多 →
CodeQL 诊断查询模板实战:用 QL 枚举数据流 Source 与 Sink,为数据扩展建模铺路

CodeQL 诊断查询模板实战:用 QL 枚举数据流 Source 与 Sink,为数据扩展建模铺路

AI 技能AI 插件应用安全网络安全AI 评测 【免费下载链接】skills Trail of Bits Claude Code skills for security research, vulnerability detection, and audit workflows 项目地址: https://gitcode.com/gh_mirrors/skills8/skills 点击查看 免费下载 本篇技术…

2026/10/10 2:30:00 阅读更多 →
Midway 2.0 定时任务触发器(Timer Trigger)实战:cron 与 every 两种定时方式详解

Midway 2.0 定时任务触发器(Timer Trigger)实战:cron 与 every 两种定时方式详解

后端微服务云原生 【免费下载链接】midway 🍔 A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate w…

2026/10/10 2:30:00 阅读更多 →
Flink Python REPL(pyflink-shell)实战指南:local / remote / YARN 模式与 Table API 交互式开发

Flink Python REPL(pyflink-shell)实战指南:local / remote / YARN 模式与 Table API 交互式开发

后端大数据流处理批处理 【免费下载链接】flink 项目地址: https://gitcode.com/gh_mirrors/fli/flink 点击查看 免费下载 Flink 仓库在部署章节(REPLs)中提供了一款集成的交互式 Python Shell(Python REPL)&#xff…

2026/10/10 2:30:00 阅读更多 →
为什么你的 Node 测试会卡死?skills 项目教你诊断 flaky 测试与悬挂进程的完整指南

为什么你的 Node 测试会卡死?skills 项目教你诊断 flaky 测试与悬挂进程的完整指南

为什么你的 Node 测试会卡死?skills 项目教你诊断 flaky 测试与悬挂进程的完整指南 【免费下载链接】skills My own collection of skills for modern Node.js development 项目地址: https://gitcode.com/gh_mirrors/skills15/skills skills 是一个面向现代…

2026/10/10 2:28:59 阅读更多 →

日新闻

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

1. 从“卫星轨道分类”这个标题说起:为什么值得花时间搞懂第一次接触“卫星轨道分类”这个概念,很多人会觉得它离自己很远——不就是天上的星星怎么转吗?但如果你正在做航天任务规划、遥感数据接收、星座设计,甚至只是准备一场航天…

2026/10/10 0:00:39 阅读更多 →
Spring AOP 核心原理与实战:从概念到日志切面落地

Spring AOP 核心原理与实战:从概念到日志切面落地

1. 从一个真实痛点说起:为什么你的代码里到处都是重复逻辑刚入行那会儿,我写过一个用户管理模块,注册、登录、改密码、注销四个接口。每个接口里都塞了几乎一样的日志打印、参数校验、事务开启和提交。当时觉得没什么,能跑就行。直…

2026/10/10 0:00:40 阅读更多 →
Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

简介:这是一套面向计算机相关专业学生与项目实战学习者的Python数据采集与分析可视化完整项目,以Boss直聘岗位数据为对象,适合用作毕业设计、课程设计或期末大作业。资源包共38个文件,约246KB,以13个py源码文件为核心&…

2026/10/10 0:00:40 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 1:36:08 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →