如何使@dataclass定义的基类与子类的__post_init__均被调用
现象原因
这个现象是Python类的方法重写规则和dataclass的代码生成逻辑共同导致的:
- 当子类定义了和父类同名的方法时,子类的方法会覆盖父类的同名实现,实例调用该方法时默认不会自动执行父类版本的逻辑
@dataclass装饰器自动生成的__init__方法,内部只会主动调用一次当前类最终生效的__post_init__方法,不会自动遍历继承链调用所有父类的__post_init__实现
示例中子类C自己定义了__post_init__,直接覆盖了父类A的同名方法,dataclass生成的初始化逻辑只会执行C类里的__post_init__给self.c赋值1,A类里给self.a赋值1的逻辑完全没被触发,所以最终打印出来a还是默认值0。
实现方案
要让实例化子类时同时执行父类和子类的__post_init__逻辑,只需要在子类的__post_init__方法中,通过super()手动调用父类的__post_init__即可,修改后的代码如下:
from dataclasses import dataclass @dataclass class A: a: int = 0 def __post_init__(self): self.a = 1 @dataclass class C(A): c: int = 0 def __post_init__(self): # 手动触发父类的__post_init__逻辑 super().__post_init__() self.c = 1
此时执行实例化打印的结果符合预期:
>>> print(C()) C(a=1, c=1)
如果是多层继承的场景,只需要每一层的__post_init__都加上super().__post_init__()调用,就会按照类的方法解析顺序(MRO)依次执行所有层级的后置初始化逻辑,和普通Python类的继承调用规则完全一致。
内容的提问来源于stack exchange,提问作者f1msch
相关产品推荐
相关产品推荐

