super()按MRO顺序委托给下一个类,确保各__init__恰好执行一次;必须所有类统一用super(),禁用硬编码调用或super(A,self),否则链断裂。

在深层多继承链中,super() 并不用于“精准追溯某个特定祖先类”,而是按方法解析顺序(MRO)自动委托给下一个协作类。它的设计目标不是跳转到某一层祖先,而是保障整条链上每个参与类的 __init__ 恰好执行一次——前提是所有类都遵循协作式初始化规范。
协作式初始化是前提
如果任意一个中间类绕过 super()、改用硬编码调用(如 Parent.__init__(self, ...)),整个链就会断裂或重复。此时 super() 就无法继续向下传递,后续类的初始化会被跳过。
- 所有类的
__init__必须统一使用super().__init__(**kwargs) - 参数必须声明为 keyword-only(即
*后参数),例如def __init__(self, *, name, **kwargs): - 每个类只处理自己关心的参数,其余无条件交给
super()
MRO 决定实际调用路径
super() 的行为完全依赖类的 MRO,它不认“血缘远近”,只认线性顺序。可通过 ClassName.__mro__ 查看真实顺序。例如:
class A: pass
class B(A): pass
class C(A): pass
class D(B, C): pass
print(D.__mro__) # → (D, B, C, A, object)
当 D().__init__() 调用 super().__init__(),它不会去找 A,而是找 MRO 中紧接 D 的 B;B 再调一次 super(),就轮到 C;C 再调,才到 A。
不要试图用 super() “指定祖先”
写 super(A, self).__init__() 是常见误区。这会强制从 A 的 MRO 中找下一个类(通常是 object),跳过 B 和 C 等中间环节,破坏协作逻辑。更严重的是,若传入字符串或非类型对象,直接报错:TypeError: super() argument 1 must be type, not str。
- ✅ 正确:所有地方都只写
super().__init__(**kwargs) - ❌ 错误:在
B中写super(A, self).__init__()或A.__init__(self)
调试与验证方法
遇到初始化异常时,优先检查三点:
- 打印子类的
__mro__,确认期望的父类是否在链中、位置是否合理 - 在每个
__init__开头加print(f"Initializing {self.__class__.__name__}"),观察实际执行顺序 - 确保每个类的
**kwargs最终能被object.__init__()安全接收(即不剩未处理参数)

















