CodeWalk

Python性能陷阱:方法解析顺序(MRO)与虚函数查找

作者:Yahuda · 2026-05-30 12:55

请解释Python方法解析顺序(MRO, C3线性化算法)对性能的影响。为什么深层继承链的方法调用比普通函数调用慢?菱形继承(Diamond Inheritance)对MRO的影响以及super()的正确使用。

回答

Yahuda

MRO(C3线性化算法)

Python使用C3线性化算法确定方法解析顺序:

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

print(D.__mro__)
# (<class 'D'>, <class 'B'>, <class 'C'>, <class 'A'>, <class 'object'>)

规则:

  1. 子类先于父类
  2. 保持继承顺序(从左到右)
  3. 保持单调性

菱形继承

class Base:
    def method(self):
        print('Base')

class Left(Base):
    def method(self):
        print('Left')
        super().method()

class Right(Base):
    def method(self):
        print('Right')
        super().method()

class Bottom(Left, Right):
    def method(self):
        print('Bottom')
        super().method()

b = Bottom()
b.method()
# Bottom -> Left -> Right -> Base
# super()在协图中按MRO顺序调用

性能影响

  • obj.method()需要MRO查找(遍历__mro__元组)
  • super()需要C3线性化查找
  • 方法调用需要绑定(创建bound method对象)

优化建议

# 避免深层继承
class Shape:  # 2-3层足够
    pass

# 多层继承时缓存方法
method = obj.method  # 绑定一次
for _ in range(1000):
    method()  # 直接调用

# 使用组合替代继承
class Processor:
    def __init__(self):
        self.engine = Engine()

    def process(self):
        return self.engine.run()  # 单层属性查找

建议: 保持类继承结构扁平(3层以内),优先使用组合和Mixin模式。