大家好,我是正在实战各种 AI 项目的程序员晚枫。
你在写类的时候,第一反应是继承还是组合? 说实话,我以前也是"继承狂魔"——能继承就继承,觉得这样代码复用率最高。后来踩了一堆坑才知道,组合才是王道 ,但继承也有它的用武之地。今天咱们就把 MRO、super()、Mixin 这些搞透彻。
🧬 MRO 方法解析顺序:多重继承的寻路地图 钻石继承问题 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class A : def method (self ): print ("A" ) class B (A ): def method (self ): print ("B" ) class C (A ): def method (self ): print ("C" ) class D (B, C): pass print (D.__mro__) d = D() d.method()
💡 MRO 是什么? Method Resolution Order,方法解析顺序。Python 使用 C3 线性化算法来确定多重继承时方法的查找顺序。你可以把它理解为一张"寻路地图"——Python 按这个顺序依次查找方法。
查看 MRO 的两种方式 1 2 3 4 5 6 7 print (D.__mro__)print (D.mro())
MRO 不合法的情况 1 2 3 4 5 6 7 8 9 10 11 12 13 14 class X : pass class Y (X ): pass class Z (Y, X): pass
🔧 super():不是调用父类,而是调用 MRO 中的下一个 super() 的真实行为 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class A : def method (self ): print ("A.method" ) super ().method() class B (A ): def method (self ): print ("B.method" ) super ().method() class C (A ): def method (self ): print ("C.method" ) class D (B, C): def method (self ): print ("D.method" ) super ().method() d = D() d.method() print (D.__mro__)
super() 在 __init__ 中的用法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Base : def __init__ (self, **kwargs ): print ("Base.__init__" ) super ().__init__(**kwargs) class A (Base ): def __init__ (self, a_val, **kwargs ): print (f"A.__init__(a_val={a_val} )" ) super ().__init__(**kwargs) class B (Base ): def __init__ (self, b_val, **kwargs ): print (f"B.__init__(b_val={b_val} )" ) super ().__init__(**kwargs) class Child (A, B): def __init__ (self, a_val, b_val, **kwargs ): print ("Child.__init__" ) super ().__init__(a_val=a_val, b_val=b_val, **kwargs) c = Child(a_val=1 , b_val=2 )
⚠️ 关键点 :super() 不是调用"父类",而是调用 MRO 链中的下一个类。配合 **kwargs 可以让所有 __init__ 都被调用到。
🧩 Mixin 模式:即插即用的功能模块 什么是 Mixin? Mixin 是一种特殊的类,它不单独使用,而是被混入到其他类中提供可选功能。它不是"is-a"关系,而是"can-do"关系。
实用 Mixin 示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import jsonclass JSONSerializableMixin : """提供 JSON 序列化功能的 Mixin""" def to_json (self ): return json.dumps(self.__dict__, ensure_ascii=False , indent=2 ) @classmethod def from_json (cls, json_str ): data = json.loads(json_str) return cls(**data) class ReprMixin : """提供友好 repr 的 Mixin""" def __repr__ (self ): class_name = self.__class__.__name__ attrs = ', ' .join(f'{k} ={v!r} ' for k, v in self.__dict__.items()) return f'{class_name} ({attrs} )' class ComparableMixin : """提供比较功能的 Mixin""" def __eq__ (self, other ): if not isinstance (other, self.__class__): return NotImplemented return self.__dict__ == other.__dict__ def __ne__ (self, other ): return not self.__eq__(other) class User (JSONSerializableMixin, ReprMixin, ComparableMixin): def __init__ (self, name, age ): self.name = name self.age = age u = User("Alice" , 30 ) print (u) print (u.to_json()) print (u == User("Alice" , 30 ))
Mixin 设计原则 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class LogMixin : """日志 Mixin""" def log (self, message ): print (f"[{self.__class__.__name__} ] {message} " ) class ValidateMixin : """验证 Mixin""" def validate (self ): for key, value in self.__dict__.items(): if value is None : raise ValueError(f"{key} 不能为空" ) return True class BadMixin : """这个 Mixin 假设宿主类有特定属性,不通用""" def process (self ): return self.data + self.config
⚖️ 继承 vs 组合:什么时候用什么 一张表看明白 维度 继承 组合 关系 is-a(是一个) has-a(有一个) 耦合度 高 低 灵活性 编译时确定 运行时可变 复用性 白盒(可见内部) 黑盒(只看接口) 适用场景 确实有层次关系 只需要某些功能
实战对比:鸭子问题 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 class Duck : def quack (self ): print ("Quack!" ) def fly (self ): print ("Flying!" ) class RubberDuck (Duck ): def quack (self ): print ("Squeak!" ) def fly (self ): raise NotImplementedError("橡皮鸭不会飞!" ) class QuackBehavior : def quack (self ): print ("Quack!" ) class SqueakBehavior : def quack (self ): print ("Squeak!" ) class MuteBehavior : def quack (self ): print ("...(沉默)" ) class FlyBehavior : def fly (self ): print ("Flying!" ) class NoFlyBehavior : def fly (self ): print ("不会飞" ) class Duck : def __init__ (self, quack_behavior, fly_behavior ): self.quack_behavior = quack_behavior self.fly_behavior = fly_behavior def perform_quack (self ): self.quack_behavior.quack() def perform_fly (self ): self.fly_behavior.fly() real_duck = Duck(QuackBehavior(), FlyBehavior()) real_duck.perform_quack() real_duck.perform_fly() rubber_duck = Duck(SqueakBehavior(), NoFlyBehavior()) rubber_duck.perform_quack() rubber_duck.perform_fly()
什么时候用继承? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Animal : def __init__ (self, name ): self.name = name class Dog (Animal ): def bark (self ): print ("Woof!" ) class Cat (Animal ): def meow (self ): print ("Meow!" ) class FlaskView : pass class MyView (FlaskView ): pass
🎯 本讲总结 MRO :C3 线性化算法决定方法查找顺序。用 __mro__ 查看,避免矛盾的继承顺序。
**super()**:不是调用父类,而是调用 MRO 中的下一个类。配合 **kwargs 确保所有 __init__ 被调用。
Mixin 模式 :提供可选功能的"即插即用"模块,单一职责、不依赖宿主内部结构。
继承 vs 组合 :优先使用组合,继承只用于真正的 is-a 关系或框架要求。
📚 推荐教材 《Python 编程从入门到实践(第 3 版)》 | 《流畅的 Python(第 2 版)》 | 《CPython 设计与实现》
学习路线: 零基础 → 《从入门到实践》 → 《流畅的 Python》 → 本门课程 → 《CPython 设计与实现》
🎓 加入《流畅的 Python》直播共读营 学到这里,如果你想系统吃透这本书——欢迎加入我的直播共读课。
每周直播精讲,逐章拆解核心知识点 专属学习群,随时答疑交流 试运营特惠:499 元 → 299 元 👉 【立即报名《流畅的 Python》共读课】 :https://mp.weixin.qq.com/s/ivHJwn1nNx5ug4TFrapvGg
🔗 课程导航 ← 上一讲:序列和多态 | 下一讲:接口与协议 →
💬 联系我 主营业务 :AI 编程培训、企业内训、技术咨询
🎓 AI 编程实战课程 想系统学习 AI 编程?程序员晚枫的 AI 编程实战课 帮你从零上手!