Python super 的查找顺序:明明写在左边父类里,为什么下一步会进入兄弟类

前天 3阅读

维护两个组合功能的父类时,常见写法是在各自的方法里调用 super。单独测试 Left,下一步进入 Root;把 Left 和 Right 组合成 Joint 后,同一行代码却先进入 Right。如果把 super 理解成“直接调用当前类声明的父类”,就会误判调用顺序。

下面所有方法只返回字符串列表,方便观察路径,没有文件、网络或共享状态。保存为 demo.py,运行 python demo.py。实验用同一个 Left.run,对比 Left 实例与 Joint 实例,并交换组合顺序再核对一次。

Python super 的查找顺序:明明写在左边父类里,为什么下一步会进入兄弟类

AI模型生成概念示意:菱形继承关系被排成一条逐站经过的查找路径;图形只辅助理解,不是解释器截图。

class Root:
    def run(self):
        return ["Root"]

class Left(Root):
    def run(self):
        return ["Left"] + super().run()

class Right(Root):
    def run(self):
        return ["Right"] + super().run()

class Joint(Left, Right):
    pass

class ReversedJoint(Right, Left):
    pass

single = Left().run()
joint = Joint().run()
reversed_joint = ReversedJoint().run()
assert single == ["Left", "Root"]
assert joint == ["Left", "Right", "Root"]
assert reversed_joint == ["Right", "Left", "Root"]
assert joint.count("Root") == 1
print("Left:", single)
print("Joint:", joint)
print("MRO:", [cls.__name__ for cls in Joint.__mro__])
print("reversed:", reversed_joint)

实例决定沿哪条顺序继续

实跑第一行是 Left: ['Left', 'Root'],第二行是 Joint: ['Left', 'Right', 'Root']。Left 的函数体没有改动,区别来自 self 的实际类型。Joint 的 MRO 依次为 Joint、Left、Right、Root、object;在 Left 内调用零参数 super,会从这条顺序中 Left 后面的位置继续查找。

因此 Right 并不需要写在 Left 的直接父类清单里,也能成为下一站。这里的零参数形式由定义方法的类和方法收到的实例共同确定查找起点。排查组合类时,先打印最终类的 __mro__,比只盯着某个父类声明更能解释真实路径。

每一站都要遵守同一个协作约定

Root.run 是这个例子的终点,返回列表后停止继续调用。Left 与 Right 都执行一次自己的工作,再把后面的结果拼接回来,所以 Root 只出现一次。如果中途某个实现不再调用 super,后续路径就会在这里断开;super 不会替遗漏的类自动补调用。

最后一行 reversed 是 ['Right', 'Left', 'Root'],说明交换组合类的父类顺序会改变协作顺序。若这些方法负责验证、修改数据或释放资源,先后次序就会影响行为,不能把父类清单当作纯粹的分类标签。

需要协作的方法应有兼容的参数与返回值约定。本例没有参数,返回值始终是列表,避免把签名冲突混进查找实验。真实代码若各层消费不同关键字参数,应明确哪些参数继续向后传递,并给链条设置接受剩余参数的合理终点。

直接点名调用会改变设计

在 Left 里写 Root.run(self) 可以明确访问指定实现,但会绕过 Joint 顺序中的 Right。这个动作适用于确实需要指定某个基类实现的设计,不能当作所有 super 问题的通用修复;混用直接调用与协作调用,还可能让共同基类重复执行。

本例证明的是方法查找与调用路径,没有证明任何多重继承结构都能成立。互相矛盾的继承顺序可能在创建类时就被拒绝。给组合组件增加测试时,应检查最终路径、每站次数和参数兼容性,而不仅是单独实例化每一个父类。

资料核对日期:2026年10月2日。示例在本地 Python 3.12.14 实际执行,全部断言通过;输出对应文中固定输入。

参考资料

文章版权声明:除非注明,否则均为云鹊BLOG原创文章,转载或复制请以超链接形式并注明出处。