Python 进阶:多重继承 MRO 与 C3 线性化算法解析
引言
Python 以'优雅'、'明确'、'简单'著称,import this(Python 之禅)中的那句 'There should be one-- and preferably only one --obvious way to do it'(应当有一种——最好只有一种——显而易见的方式来做它)被无数开发者奉为圭臬。
然而,在 Python 的面向对象编程(OOP)深水区,隐藏着一个让许多资深开发者都感到头疼,却又无比精妙的机制——多重继承(Multiple Inheritance)与方法解析顺序(Method Resolution Order, MRO)。
你是否遇到过这样的困惑:
- 为什么在复杂的继承关系中,
super()调用的不是父类,而是兄弟类? - 当菱形继承(Diamond Problem)出现时,Python 是如何避免无限递归和逻辑冲突的?
- 为什么 Python 2.3 之后抛弃了经典类的深度优先搜索,转而采用了 C3 线性化算法?
今天,我们将剥开 Python 面向对象系统的外衣,直击其核心的 DNA——MRO。这不仅仅是关于语法的讨论,更是一场关于算法美学与架构设计的探索。
第一部分:多重继承的挑战
在单继承语言(如 Java 的类继承)中,寻找一个方法非常简单:如果当前类没有,就去父类找,一直追溯到 Object。这就像一条单行道,绝无分岔。
但在 Python 这种支持多重继承的语言中,情况变得扑朔迷离。请看下面这个经典的菱形继承结构:
class A:
def save(self):
print("A save")
class B(A):
def save(self):
print("B save")
class C(A):
def save(self):
print("C save")
class D(B, C):
pass
如果 D 没有实现 save 方法,它该调用 B 的还是 C 的?如果 B 和 C 都调用了 A.save(),A 的方法会被执行两次吗?
在早期的 Python(经典类)中,采用的是简单的。在这种策略下,路径是 。这导致了一个严重问题:。


