super只能调用父类方法或初始化实例/类属性,不传递局部变量;局部变量作用域限于函数内,仅赋值给self.xxx才成为可继承的实例属性。

不能靠继承获取父类方法里的局部变量,super 只能调用方法、初始化实例属性或类属性,它不传递、不复制、也不“继承”函数内部的局部作用域。所谓“覆盖引发的属性引用误区”,本质是混淆了局部变量、实例属性和类属性三者的生命周期与可见范围。
明确区分局部变量与实例属性
父类 __init__ 中用 name = "xxx" 定义的是局部变量,函数结束即销毁;只有赋值给 self.xxx 的才是实例属性,才能被子类通过 self.xxx 访问。
- 错误写法:
def __init__(self): msg = "hello"; print(msg)→ 子类调super().__init__()后仍无法访问msg - 正确写法:
def __init__(self): self.msg = "hello"; print(self.msg)→ 子类可直接使用self.msg
super() 调用后务必检查实例属性是否真正创建
即使写了 super().__init__(),如果父类 __init__ 内部没把值存到 self 上,子类就拿不到。常见于调试时误把打印语句当初始化。
- 例如:父类中
def __init__(self): result = calculate(); print(result)→result是局部变量,子类访问self.result会报AttributeError - 修复方式:改为
self.result = calculate()
多重继承下避免 MRO 导致的初始化遗漏
多个父类都有 __init__ 时,仅靠一个 super().__init__() 不保证所有父类都被执行——必须每个父类的 __init__ 都含 super(),否则链式调用会在某处中断,某些父类的实例属性根本不会设置。
- 典型症状:子类能访问 A 类的
self.a,但访问不到 B 类的self.b,尽管两者都声明了class C(A, B): ... - 验证方式:打印
C.__mro__,再逐个确认各父类__init__是否含super().__init__()
dataclass 场景下需特别注意字段继承顺序
使用 @dataclass 时,父类字段自动成为子类实例属性,但若父类字段未带默认值,而子类新增字段带了默认值,Python 会报错 —— 这不是 super 的问题,而是 dataclass 的字段排序规则强制要求“无默认值字段必须在有默认值字段之前”。
- 错误示例:父类
@dataclass含name: str(无默认),子类加id: int = 0→ 报TypeError - 解决办法:要么给父类字段加默认值,要么子类所有字段都不设默认值,或改用
field(default_factory=...)











