Python dataclass继承重写字段默认值为何需添加类型注解?
这不是使用方式错误,是Python dataclass的内置字段识别规则决定的必然行为。
dataclass字段的判定规则
dataclass装饰器在处理类、生成构造方法和字段元数据时,仅会将带有类型注解的类属性识别为dataclass字段。没有类型注解的类属性,无论名称是什么,都会被当作普通类属性处理,完全不会进入dataclass的字段解析、重写逻辑。
对应两种写法的实际执行逻辑
无类型注解的写法:
你在Test2中写的text = "Overwritten"没有类型注解,dataclass处理Test2时不会将其识别为字段,只会直接从父类Test继承原有的text字段定义,默认值保留为"Test"。
这行代码实际只是给Test2类绑定了一个普通类属性,可以通过类名直接访问到这个值,但实例化时,dataclass生成的__init__方法会给实例绑定同名的实例属性text="Test",实例属性优先级高于类属性,最终打印实例属性时拿到的还是父类定义的默认值。
可以用这段代码验证这个逻辑:from dataclasses import dataclass @dataclass class Test: text:str = "Test" @dataclass class Test2(Test): text = "Overwritten" print(Test2.text) # 输出 Overwritten,访问的是普通类属性 b = Test2() print(b.text) # 输出 Test,访问的是构造方法绑定的实例属性加类型注解的写法:
当你在Test2中写text:str = "Overwritten"时,dataclass扫描到这个带类型注解的同名属性,会判定这是对父类text字段的重写,自动用新的默认值替换父类继承来的旧默认值,最终生成的构造方法中text参数的默认值就是"Overwritten",实例化后实例属性自然是新值,符合预期。
额外注意事项
重写继承的dataclass字段时,哪怕你不需要修改字段类型,也必须保留类型注解,否则重写不会生效。另外如果子类重写字段时只加了类型注解、没有设置默认值,该字段会被识别为无默认值的必填字段,父类原有的默认值会被覆盖,实例化时不传参会直接报错。
内容的提问来源于stack exchange,提问作者Austin Witherspoon

