super() 是代理对象而非构造器,调用父类 init 时须严格匹配其参数签名;多继承中应统一用 super() 配合 **kwargs 协作初始化,避免手动指定父类名或漏传参数。
在 python 中,super() 不是构造器,而是一个代理对象,用于调用父类(或 mro 中下一个类)的方法。子类初始化时若需手动触发父类的**特定有参 __init__ 逻辑**,关键在于:明确父类 __init__ 的参数签名,并通过 super().__init__(...) 传入对应实参。
确认父类 __init__ 的参数要求
必须先看清父类如何定义初始化逻辑。例如:
class Animal:
def __init__(self, name, species):
self.name = name
self.species = species
print(f"Animal created: {name} ({species})")
这个 Animal.__init__ 明确需要两个位置参数:name 和 species。子类调用时不能遗漏、不能错序、类型也应兼容。
在子类 __init__ 中显式使用 super() 传参
子类自己的 __init__ 可以定义不同参数,但内部必须用 super().__init__(...) 把父类所需参数“组装好”并传入:
class Dog(Animal):
def __init__(self, name, breed, age):
# 将子类参数映射为父类所需参数
super().__init__(name=name, species="Canis lupus familiaris")
self.breed = breed
self.age = age
这里:
• name 直接复用;
• species 固定传入字符串,不依赖子类参数;
• age 和 breed 是子类特有属性,由子类自行处理。
处理多继承与 MRO 顺序
当存在多个父类时,super() 按 MRO(方法解析顺序)调用下一个类的 __init__。所有参与的类最好都使用 super() 配合 **kwargs 或约定参数名,避免参数传递断裂:
- 推荐写法(协作式初始化):
class A:
def __init__(self, x, **kwargs):
super().__init__(**kwargs) # 继续链式调用
self.x = x
<p>class B:
def <strong>init</strong>(self, y, <strong>kwargs):
super().<strong>init</strong>(</strong>kwargs)
self.y = y</p><p>class C(A, B):
def <strong>init</strong>(self, x, y, z):
super().<strong>init</strong>(x=x, y=y) # 自动按 MRO 分发
self.z = z
这样能确保每个父类都收到自己关心的参数,且不因顺序变化而报错。
常见误区提醒
-
不要写
super().__init__后加括号却不传参——如果父类__init__要求参数,空调用会直接抛TypeError; -
不要混用
ParentClass.__init__(self, ...)和super()——破坏协作机制,尤其在多继承中易出错; -
子类
__init__不写super()调用,父类初始化逻辑就完全不会执行——属性未设置、副作用未触发,可能引发后续 AttributeError 或逻辑错误。

















