Python性能陷阱:方法解析顺序(MRO)与虚函数查找
请解释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'>)
规则:
- 子类先于父类
- 保持继承顺序(从左到右)
- 保持单调性
菱形继承
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模式。