Python 多重继承与 MRO
多重继承用 C3 线性化得到 MRO;super 沿 MRO 协作,混入(mixin)应保持正交。
#concept
#growing
#dev
#python
#python
[!info] related notes
Python 多重继承与 MRO
这个概念为什么出现
日志混入、权限混入、序列化混入……多重继承能拼能力,但若查找顺序不明,会出现“调到了意料外的实现”。Python 用 C3 线性化生成 MRO(Method Resolution Order)。
[!abstract] 一句话理解 多基类时属性查找按
Cls.__mro__顺序;super()走向 MRO 中的下一个类,使混入可协作。
最小可运行示例
先把示例放进业务场景,再看代码:
场景:API Handler 混入鉴权与审计
# mro_mixin_demo.py
# 业务意图:AuthMixin + AuditMixin 叠在 Handler 上。
# 教学点:
# - __mro__ 顺序;
# - super 协作链;
# - mixin 应调用 super。
class Handler:
def handle(self, req: str) -> str:
return f"handle:{req}"
class AuditMixin:
def handle(self, req: str) -> str:
return "audit|" + super().handle(req)
class AuthMixin:
def handle(self, req: str) -> str:
if not req.startswith("ok:"):
return "deny"
return "auth|" + super().handle(req)
class ApiHandler(AuthMixin, AuditMixin, Handler):
pass
def main() -> None:
print(ApiHandler.__mro__)
print(ApiHandler().handle("ok:pay"))
print(ApiHandler().handle("bad"))
if __name__ == "__main__":
main()
建议运行:
python mro_mixin_demo.py
期望输出(MRO 元组含类对象 repr):
(<class '__main__.ApiHandler'>, <class '__main__.AuthMixin'>, <class '__main__.AuditMixin'>, <class '__main__.Handler'>, <class 'object'>)
auth|audit|handle:ok:pay
deny
结合场景再看三个关注点
- 基类书写顺序影响 MRO:
AuthMixin在AuditMixin前。 - 要继续协作链的方法应调用
super(),签名也需兼容;终点Handler刻意不再转发,拒绝分支也会主动终止。 - 拒绝分支不进入
AuditMixin,因此连演示中的审计步骤也被跳过;若需要记录拒绝,必须调整次序或显式记录。字符串前缀仅模拟授权条件,不能用于真实鉴权。
核心概念与准确模型
- 查看:
Class.__mro__或Class.mro() - C3:既保持局部优先级又保持单调性
- 无法线性化时类创建失败
边界情况与反直觉行为
- 父类顺序冲突导致
TypeError: Cannot create a consistent method resolution order - 菱形继承的 MRO 中每个类只出现一次,但不保证方法只执行一次:重复调用
super或直接调用基类方法仍会重复执行。 - mixin 带状态易变乱——优先无状态 mixin
常见误区
[!warning] 常见误区:多重继承是默认设计 错误理解:能力多就多继承。
正确模型:组合、协议、装饰器往往更清晰;mixin 要正交且文档化 MRO 预期。
工程实践
- 命名
XxxMixin - 只混入行为,不混入复杂构造参数
- 用断言检查关键 MRO 顺序与允许/拒绝路径的实际调用;打印本身不会防止回归
本节总结
MRO 是多重继承的地图;super 是沿地图前进的方式。先会读 __mro__,再写 mixin。
自测题
- 如何查看查找顺序?
- mixin 为什么要调用 super?
参考答案
Cls.__mro__。- 把控制权交给 MRO 下一类型,形成协作链。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| C3 method resolution | 历史文档 | C3 说明 |
| Data model – MRO | 规范 | 类型对象 |