(九)super() 与方法解析顺序
只看单继承时,容易把 super() 理解为“固定访问代码里写出的父类”。多个类一起参与继承时,它的含义要沿方法解析顺序(MRO)阅读。
# 两个中间类都把当前对象的调用继续交给 MRO 中的下一个实现。
class Root:
def describe(self):
return ["Root"]
class Labelled(Root):
def describe(self):
return ["Labelled"] + super().describe()
class Tracked(Root):
def describe(self):
return ["Tracked"] + super().describe()
class Combined(Labelled, Tracked):
pass
print([cls.__name__ for cls in Combined.__mro__])
print(Combined().describe())输出:
['Combined', 'Labelled', 'Tracked', 'Root', 'object']
['Labelled', 'Tracked', 'Root']
__mro__ 保存实际查找顺序,object 是普通 Python 类最终继承到的基类。调用先在 Labelled 找到实现;其中的 super() 从 Labelled 在这个实例 MRO 中的位置之后继续,下一站是 Tracked,再从 Tracked 继续到 Root。
因此 Labelled 中的 super() 在这次调用里找到了 Tracked,而不是它定义处直接写出的 Root。整条调用链保持同一个实例;每一层再决定是否继续调用下一层。读到已有代码的多重继承时,先列出 __mro__,再逐条跟踪调用,返回时合并各层结果。super 的查找规则
普通业务记录用单继承或组合就能表达的关系,可以直接按那种方式组织。引入多个基类时,需要把共同方法的参数和继续调用方式一起安排好,避免只看类名就猜执行顺序。