下面讲python中,
__init__在继承里最常见、最容易踩的坑
核心一句话
子类写了 __init__,就不会自动调用父类 __init__
父类的初始化代码不会自动跑,属性、逻辑都会丢。
坑 1:子类写了 init ,但没调用父类 init
错误代码
python
class Animal:
def __init__(self):
print("父类初始化")
self.age = 10 # 父类属性
class Dog(Animal):
def __init__(self):
print("子类初始化")
# 这里没调用父类 __init__!
dog = Dog()
print(dog.age) # 报错!AttributeError
为什么错?
- 子类自己写了
__init__ - Python 不会自动帮你调父类的
__init__ - 所以
self.age根本没被创建 - 访问就报错
正确写法
python
class Dog(Animal):
def __init__(self):
super().__init__() # 手动调用父类初始化
print("子类初始化")
坑 2:父类 init 需要参数,子类没传
错误代码
python
class Animal:
def __init__(self, age):
self.age = age
class Dog(Animal):
def __init__(self):
super().__init__() # 没传 age!
运行直接报错:
TypeError: __init__() missing 1 required positional argument: 'age'
正确写法
python
class Dog(Animal):
def __init__(self):
super().__init__(10) # 传参
坑 3:以为 super() 必须带类名和 self(老写法误区)
Python3 里下面两种完全一样:
python
super().__init__()
# 老写法(Python2 遗留)
super(Dog, self).__init__()
你只需要记:
Python3 直接写 super().__init__() 就够了
坑 4:多继承时 super() 调用顺序混乱(菱形问题)
这个是最难、最容易懵的坑。
python
class A:
def __init__(self):
print("A")
class B(A):
def __init__(self):
print("B")
super().__init__()
class C(A):
def __init__(self):
print("C")
super().__init__()
class D(B, C):
def __init__(self):
print("D")
super().__init__()
d = D()
你以为执行顺序是:
D → B → A
D → C → A
实际输出:
D
B
C
A
为什么?
因为 Python 多继承用 MRO 方法解析顺序
super() 不是"只调父类",而是按 MRO 链找下一个。
结论
多继承里 super() 行为很诡异,尽量少用多继承
这也是为什么设计原则说:优先组合,少用继承
坑 5:子类 init 里还没 super 就用父类属性
python
class Animal:
def __init__(self):
self.age = 10
class Dog(Animal):
def __init__(self):
print(self.age) # 报错!还没初始化
super().__init__()
必须先调用 super().__init__(),才能用父类属性。
最核心总结(背这几句就够)
- 子类写
__init__,必须手动调用super().__init__() - 父类要参数,子类必须传
- 先
super(),再用父类属性 - 多继承
super()顺序诡异 → 尽量不用多继承 - 子类不写
__init__→ 自动用父类的,不会踩坑