Python 语法精炼18
继承
在 Python 中,类可以从一个或多个父类继承:
1 | class Parent: |
当一个类从多个父类继承时,这就是多重继承。
1 | class A: pass |
C 同时继承了 A 和 B。
MRO
MRO(方法解析顺序):
是指 Python 在多重继承中搜索属性和方法的顺序。
当你访问 obj.method() 时,Python 会按一定的顺序在类的继承链上查找 method,这个顺序由 MRO 列表 决定。
查看 MRO
两种常用方法:
1 | C.__mro__ # 返回一个元组 |
示例:
1 | class A: pass |
解释:
Python 会优先从当前类开始,然后按 MRO 顺序依次查找父类。
计算方式
Python 3 使用 C3 Linearization 算法 来计算 MRO。
它的核心规则是:
- 自己优先,子类优先于父类;
- 保持继承声明顺序;
- 保证继承一致性,不会破坏父类顺序。
📘 举例:经典菱形继承问题
1 | class A: |
输出:
1 | B |
✅ 解释:
- Python 查找顺序:D → B → C → A → object;
- 虽然 A 是共同父类,避免重复调用,但只会执行一次;
- 这就是 C3 MRO 的结果。
super() 用法
super() 是用来根据 MRO 顺序调用下一个类的方法的函数。
基本用法
1 | class Parent: |
输出:
1 | Hello from Parent |
✅ super() 根据 MRO 调用“下一个”类的同名方法,而不是“父类固定名字”。
真正威力
1 | class A: |
输出:
1 | D |
✅ 解释:
- MRO 决定了调用链顺序:
D → B → C → A → object; - 每个类的
super().show()都按照 MRO 链往后找; - 不会重复调用同一个类,例如
A.show()只执行一次。
👉 所以 super() 并不是“调用父类”,而是“根据 MRO 查找下一个类”。
底层机制
在底层,super() 实际上做了两件事:
1 | super(CurrentClass, self) |
- 取出
self的 MRO; - 从 MRO 中找到
CurrentClass之后的下一个类; - 从那个类开始继续查找方法。
🔍 验证:
1 | print(D.mro()) |
用 super() 而不是写父类名?
错误写法:
1 | class B(A): |
问题:
- 会固定调用指定父类,不遵循MRO。
- 在多重继承中,可能破坏调用链,导致重复调用或遗漏。
正确写法:
1 | super().show() # ✅ 自动遵循 MRO,安全 |
混合继承
Mixin 类通常用来组合功能,不会单独实例化,使用 super() 能确保每个 Mixin 的方法都能被执行一次。
示例:
1 | class LogMixin: |
输出:
1 | Logging... |
✅ 所有类的方法都执行了一次,顺序由 MRO 控制。
菱形继承
1 | A |
MRO: [D, B, C, A, object]
super() 调用顺序:
1 | D.show() → B.show() → C.show() → A.show() |
每个类都只执行一次。
总结表
| 概念 | 含义 | 关键点 |
|---|---|---|
| MRO | 方法解析顺序 | 决定属性/方法查找路径 |
| 算法 | C3 线性化 | 保证一致性和单次调用 |
| super() | 调用 MRO 链中的下一个类 | 不直接指向父类 |
| 单继承 | super() = 父类调用 |
简单 |
| 多继承 | super() = 按 MRO 向后 |
避免重复调用 |
| 不推荐 | Parent.method(self) |
会破坏 MRO 链 |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Telason!
