人人都会AI编程

单继承、多继承、MRO 方法解析顺序

更新时间:2026-07-12

Python 在继承上的设计既灵活又讲究规则,理解单继承、多继承以及方法解析顺序(MRO)是正确使用面向对象和避免踩坑的关键。

单继承

单继承就是一个子类只从一个父类派生,逻辑清晰、控制直接。

class Animal:
    def speak(self):
        return "动物叫声"

class Dog(Animal):
    def speak(self):
        return "汪汪"

d = Dog()
print(d.speak())   # 汪汪
  • 子类可以复用父类的方法和属性,也可以覆盖(重写)它们。
  • 使用 super() 可以在重写时调用父类的方法,避免重复编码:
class Cat(Animal):
    def speak(self):
        base = super().speak()     # 调用父类的 speak
        return f"{base} - 喵喵"

单继承是项目中使用最广泛的继承方式,结构扁平、易于理解和维护。

多继承

多继承允许一个子类同时从多个父类派生,可以在一个类中组合多个来源的功能。

class Flyable:
    def fly(self):
        return "飞"

class Swimmable:
    def swim(self):
        return "游"

class Duck(Flyable, Swimmable):
    pass

d = Duck()
print(d.fly())    # 飞
print(d.swim())   # 游
  • 多继承非常强大,但也容易导致菱形继承(一个类通过两条不同路径继承同一个基类)或方法冲突。
  • 为了避免混乱,必须清楚 Python 是如何决定“到底调用哪个方法”的,答案就是 MRO。

MRO 方法解析顺序

MRO(Method Resolution Order)是 Python 计算出的属性、方法查找顺序。当一个实例调用 obj.method() 时,Python 会按照 MRO 列表从当前类开始,逐级向上查找对应的方法。

C3 线性化算法
Python 使用C3 线性化算法来计算新式类(Python 3 中所有类都是新式类)的 MRO,它保证:

  • 子类始终在父类之前。
  • 父类的顺序与定义时的顺序一致。
  • 对于复杂的菱形继承,仍能生成单调、无歧义的查找顺序。

查看一个类的 MRO 有两种方式:

class A: pass
class B(A): pass
class C(A): pass
class D(B, C): pass

print(D.__mro__)
# (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
print(D.mro())
# 同样的输出,但返回列表

一个经典的菱形继承示例

      A
     / \
    B   C
     \ /
      D

对应代码:

class A:
    def method(self):
        return "A"

class B(A):
    def method(self):
        return "B"

class C(A):
    def method(self):
        return "C"

class D(B, C):
    pass

print(D().method())   # B,因为 MRO 中 B 在 C 前
print(D.__mro__)
# (D, B, C, A, object)
  • D 中未定义 method,Python 会按顺序找 B,找到了就调用 B.method()
  • 如果 BC 都没有定义,会最终找到 A

super() 与 MRO 的配合
super() 并不是直接调用父类方法,而是按照 MRO 顺序查找下一个类的方法。这在多继承场景下非常重要:

class A:
    def method(self):
        print("A")

class B(A):
    def method(self):
        print("B")
        super().method()

class C(A):
    def method(self):
        print("C")
        super().method()

class D(B, C):
    def method(self):
        print("D")
        super().method()

D().method()
# 输出顺序:
# D
# B
# C
# A

因为 D 的 MRO 是 D -> B -> C -> A -> objectsuper().method() 严格沿着这个顺序执行,这才保证了协作式多继承时每个类的方法都能按顺序被调用。

设计建议

  • 能用组合代替继承的场景,优先使用组合(把一个类的对象作为另一个类的属性)。
  • 多继承尽量使用 Mixin 类:Mixin 是一个只提供特定功能、不应当单独实例化的类,它自身没有复杂的继承链,只是“混入”功能。
  • 显式声明 super().init() 并在多继承时保持参数一致性,避免因为参数不匹配导致运行时错误。
  • 如果发现 MRO 让你困惑,那块代码很可能需要重构以减少复杂度。

掌握 MRO,你就能自信地设计多继承类结构,写出行为可预测、可维护的 Python 代码。