super() 严格按 MRO 顺序调用下一个类方法,不支持精准定向父类;其本质是顺位委托,需通过协作式初始化协议(关键字参数+无损传递)确保多继承中各父类有序、不重复执行。

super 关键字在多重继承中不支持“精准定向”某个特定父类——它从不跳转、不指定、不绕过,而是严格遵循当前类的 MRO(Method Resolution Order)顺序,调用链条中“下一个”类的方法。所谓“精准定向父类上下文”,本质上是对 super 机制的常见误解;真正可控的是设计好继承结构和初始化协议,让 MRO 按需展开。
理解 super 的本质:MRO 下的顺位委托
super() 不是“找父类”,而是“找 MRO 序列里当前类之后的下一个类”。这个顺序由 C3 线性化算法决定,可通过 ClassName.mro() 查看。例如:
-
D(B, C) 的 MRO 是
[D, B, C, A, object](假设 B 和 C 都继承自 A) - 在 D.__init__() 中写 super().__init__(),实际调用的是 B.__init__()
- 在 B.__init__() 中写 super().__init__(),实际调用的是 C.__init__()
- 在 C.__init__() 中写 super().__init__(),实际调用的是 A.__init__()
避免手动指定类名:否则破坏 MRO 协作
显式写 ParentClass.__init__(self, ...) 或 super(ParentClass, self).__init__() 会切断委托链:
- 前者完全绕过 MRO,硬编码调用,导致其他父类(如另一条继承路径上的类)被跳过
- 后者若传入非当前类或非实例所属类,会触发 TypeError: super() argument 1 must be type
- 两者都无法兼容协作式初始化,尤其在钻石继承中极易引发重复调用或遗漏
实现可控上下文的关键:协作式初始化协议
要让多个父类有序参与初始化,所有类必须统一采用以下模式:
- 参数全部声明为仅关键字参数(keyword-only),如 def __init__(self, *, name, **kwargs):
- 每个类只消费自己需要的参数,其余通过 super().__init__(**kwargs) 无损传递
- 最顶层基类(通常是 object)接收空 kwargs 并静默结束
- 子类按需组合参数,例如 Flat(street="Main", number=12, country="CN", price=800000)
验证与调试:主动查看和测试 MRO 行为
不要靠猜测,而要用工具确认实际调用路径:
- 打印 MyClass.mro() 查看完整解析顺序
- 在各 __init__ 开头加 print("In ClassX"),观察执行流是否符合 MRO
- 检查是否所有父类 __init__ 都被执行且仅执行一次——这是协作初始化成功的标志


















