文章目录
多继承是面向对象编程中的一个强大特性,它允许一个子类同时继承多个父类。 Python 是少数几种支持多继承的主流语言之一。
1. 基本语法
class Father:
def skills(self):
print("园艺、编程")
class Mother:
def skills(self):
print("烹饪、音乐")
# Child 类同时继承 Father 和 Mother
class Child(Father, Mother):
def own_skill(self):
print("体育")
c = Child()
c.skills() # 输出:园艺、编程
c.own_skill() # 输出:体育
MRO 顺序:Child → Father → Mother → object
2. 方法解析顺序 - MRO
当多个父类都有同名的方法时(如上例中的 skills),Python 需要确定调用哪一个。这个顺序由 方法解析顺序 决定。
- MRO 原则:Python 2.3 以后使用 C3 线性化算法
- 查看 MRO:使用
类名.__mro__或类名.mro()
print(Child.__mro__)
# 输出:(<class '__main__.Child'>, <class '__main__.Father'>, <class '__main__.Mother'>, <class 'object'>)
MRO 的执行顺序是:
- 先在自己的类中查找
- 然后在第一个父类中查找
- 接着按顺序在后续父类中查找
- 最后在 object 类中查找
3. 经典问题:菱形继承(钻石问题)
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
d = D()
d.method() # 输出什么?
print(D.__mro__)
MRO 顺序:D → B → C → A → object
输出结果:
B
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
解析:
- 按照 MRO 顺序:D → B → C → A → object
- 在 B 中找到了
method,所以输出 “B”
4. super() 函数在多继承中的使用
super() 会按照 MRO 顺序调用下一个类的方法:
class A:
def __init__(self):
print("A init")
class B(A):
def __init__(self):
print("B init")
super().__init__()
class C(A):
def __init__(self):
print("C init")
super().__init__()
class D(B, C):
def __init__(self):
print("D init")
super().__init__()
d = D()
输出结果:
D init
B init
C init
A init
执行流程:
- D 的
__init__调用super().__init__() - 按 MRO 找到 B 的
__init__ - B 的
__init__调用super().__init__() - 按 MRO 找到 C 的
__init__ - C 的
__init__调用super().__init__() - 按 MRO 找到 A 的
__init__
5. 混入类
混入类是一种常用的多继承设计模式,用于为其他类提供额外功能:
# 混入类 - 通常以 Mixin 结尾
class JsonSerializableMixin:
def to_json(self):
import json
return json.dumps(self.__dict__)
class LoggerMixin:
def log(self, message):
print(f"[LOG] {message}")
class Person:
def __init__(self, name):
self.name = name
# 通过多继承混入功能
class Employee(JsonSerializableMixin, LoggerMixin, Person):
def __init__(self, name, salary):
super().__init__(name)
self.salary = salary
emp = Employee("Alice", 50000)
print(emp.to_json()) # 来自 JsonSerializableMixin
emp.log("上班打卡") # 来自 LoggerMixin
MRO 顺序:Employee → JsonSerializableMixin → LoggerMixin → Person → object
6. 最佳实践和建议
- 谨慎使用多继承:过度使用会让代码复杂难懂
- 优先使用组合:考虑是否能用组合关系代替继承
- 使用混入模式:为类添加横切关注点的功能
- 明确接口:确保理解每个父类的职责
- 注意 MRO:在设计复杂继承关系时要清楚 MRO 顺序
7. 实际应用场景
# 实际应用:自定义异常类
class ValidationError(ValueError, TypeError):
"""既包含值错误也包含类型错误的验证异常"""
pass
# 实际应用:Django 的视图类
class MyView(TemplateView, FormView):
"""同时具备模板渲染和表单处理功能"""
pass
总结
Python 的多继承:
- ✅ 优点:代码复用性强,功能组合灵活
- ⚠️ 缺点:复杂度高,容易造成设计混乱
- 🎯 关键:理解 MRO 机制,合理使用混入模式
多继承是一个强大的工具,但需要谨慎使用。在大多数情况下,组合或单一继承可能是更清晰的选择。
MRO 计算规则总结
Python 的 C3 线性化算法遵循三个原则:
- 子类优先于父类
- 继承列表中靠前的类优先
- 保持单调性(如果一个类在 MRO 中出现在另一个类之前,那么在所有相关子类中都保持这个顺序)

1393

被折叠的 条评论
为什么被折叠?



