本文目录导读:
我来通过一个具体的源码案例来剖析Python的属性查找MRO(Method Resolution Order)算法。
案例设计
我们设计一个经典的菱形继承结构,并添加一些特殊方法来观察MRO的执行过程:
class A:
def method(self):
print(f"A.method called from {self.__class__.__name__}")
return "A"
class B(A):
def method(self):
print(f"B.method called from {self.__class__.__name__}")
# 主动调用父类方法
result = super().method()
return f"B -> {result}"
class C(A):
def method(self):
print(f"C.method called from {self.__class__.__name__}")
result = super().method()
return f"C -> {result}"
class D(B, C):
def method(self):
print(f"D.method called from {self.__class__.__name__}")
result = super().method()
return f"D -> {result}"
核心源码剖析
MRO的计算过程
def compute_mro(cls):
"""
模拟Python的C3线性化算法
"""
if cls is object:
return [object]
# 获取父类的MRO
bases_mros = [compute_mro(base) for base in cls.__bases__]
# C3线性化算法核心
result = [cls]
while bases_mros:
# 选择合适的主父类
chosen = None
for mro in bases_mros:
if mro and mro[0] not in [lst[1:] for lst in bases_mros]:
chosen = mro[0]
break
if chosen is None:
raise TypeError("Inconsistent MRO")
result.append(chosen)
# 移除已选择的类
for mro in bases_mros:
if mro and mro[0] == chosen:
mro.pop(0)
# 删除空的MRO列表
bases_mros = [mro for mro in bases_mros if mro]
return result
自定义MRO查看器
class MROInspector:
"""
MRO底层实现剖析器
"""
@staticmethod
def inspect_mro(cls):
"""深度剖析类的MRO"""
print(f"{'='*60}")
print(f"类 {cls.__name__} 的MRO分析:")
print(f"{'='*60}")
# 1. 查看标准MRO
print(f"\n1. 标准MRO顺序:")
for i, c in enumerate(cls.__mro__):
print(f" [{i}] {c.__name__}")
# 2. 查看继承层次
print(f"\n2. 继承关系:")
MROInspector._print_hierarchy(cls, 0)
# 3. 查看方法解析过程
print(f"\n3. 方法查找路径:")
MROInspector._trace_method_lookup(cls, "method")
@staticmethod
def _print_hierarchy(cls, level):
"""打印继承层次"""
indent = " " * level
print(f"{indent}└── {cls.__name__}")
for base in cls.__bases__:
if base is not object:
MROInspector._print_hierarchy(base, level + 1)
@staticmethod
def _trace_method_lookup(cls, method_name):
"""追踪方法查找路径"""
print(f" 查找 '{method_name}' 方法的路径:")
for i, c in enumerate(cls.__mro__):
if method_name in c.__dict__:
print(f" ✓ [{i}] {c.__name__} - 找到方法")
break
else:
print(f" ✗ [{i}] {c.__name__} - 未找到")
else:
print(f" 方法 '{method_name}' 在所有类中都未找到")
完整的验证测试
def main():
# 首先查看MRO
print("=== MRO计算分析 ===")
print(f"D的MRO: {[c.__name__ for c in D.__mro__]}")
print(f"B的MRO: {[c.__name__ for c in B.__mro__]}")
print(f"C的MRO: {[c.__name__ for c in C.__mro__]}")
# 使用MRO查看器
inspector = MROInspector()
inspector.inspect_mro(D)
# 测试方法调用链
print(f"\n=== 方法调用测试 ===")
d = D()
result = d.method()
print(f"\n最终结果: {result}")
# 演示super()的底层机制
print(f"\n=== super()底层机制 ===")
print(f"super(D, d)的类型: {type(super(D, d))}")
print(f"super(D, d)的MRO: {super(D, d).__thisclass__}")
print(f"super()在MRO中的位置:")
# 展示super()如何查找下一个类
mro = D.__mro__
for i, cls in enumerate(mro):
if cls is D:
print(f" D在MRO中的索引: {i}")
if i + 1 < len(mro):
print(f" 下一个被查找的类: {mro[i+1].__name__}")
break
运行结果解读
执行上述代码后,你会看到:
=== MRO计算分析 ===
D的MRO: ['D', 'B', 'C', 'A', 'object']
B的MRO: ['B', 'A', 'object']
C的MRO: ['C', 'A', 'object']
MRO的关键特性:
- 本地优先:先检查当前类
- 继承顺序:按照父类声明顺序
- 单调性:子类的MRO保留父类的MRO顺序
- 避免重复:每个类只出现一次
深入理解super()的底层实现
def _super_implementation(cls, instance):
"""
super()的简化实现原理
"""
def find_method(method_name):
# 获取实例的MRO
mro = type(instance).__mro__
# 找到当前类在MRO中的位置
current_idx = mro.index(cls)
# 从下一个类开始查找
for next_cls in mro[current_idx + 1:]:
if method_name in next_cls.__dict__:
# 绑定方法到实例
method = next_cls.__dict__[method_name]
if hasattr(method, '__get__'):
return method.__get__(instance, type(instance))
return method
raise AttributeError(f"方法 {method_name} 未找到")
return type('super', (), {'__getattr__': lambda self, name: find_method(name)})()
关键源码分析总结
-
C3线性化算法:
- Python使用C3算法计算MRO
- 保证单调性和一致性
- 通过拓扑排序确定类顺序
-
方法查找过程:
- 按MRO顺序逐个检查
- 找到第一个包含该方法的类
- 使用描述器协议绑定方法
-
super()的工作机制:
- 不是简单的父类调用
- 基于MRO的下一跳
- 保持协作式多继承的正确性
这个案例通过实践代码和底层分析,帮助你深入理解Python的MRO算法和属性查找机制。