Python dataclass用dict作字段默认值报ValueError的解决方法
报错根因
dataclass 会主动拦截可变类型(dict、list、set 等)直接作为字段默认值的写法,规避 Python 类定义里经典的可变默认值坑:如果直接给字段赋值字典作为默认值,所有类实例会共享同一个字典对象,单个实例修改该字段时,其余实例的对应值会被意外篡改。
你的代码里还有两处会导致运行/类型错误的问题:
headers字段的类型注解标注为str,实际赋值为字典,类型不匹配main方法定义在Application类外部,直接调用app.main()会抛出属性不存在的异常
字典字段的正确初始化方式
使用dataclasses.field()的default_factory参数声明可变类型默认值即可。该参数接收一个无参可调用对象,每次实例化类时都会调用该对象生成全新的独立实例,从根源上避免多实例共享可变对象的问题。
- 空字典字段:直接传内置类型
dict即可,写法为headers: dict = field(default_factory=dict) - 带初始值的字典字段:传无参lambda,返回你需要的初始字典内容
修正后的可运行代码如下:
from configparser import ConfigParser from dataclasses import dataclass, field @dataclass class Application: # 类级公共配置,无类型注解不会被识别为dataclass实例字段,所有实例共享 __config = ConfigParser() __config.read('mydb.ini') __host: str = __config.get('db', 'dbhost') __user: str = __config.get('db', 'dbuser') __password: str = __config.get('db', 'dbpw') __database: str = __config.get('db', 'database') url: str = "https://xxxx.domain.com/" # 修正类型注解,通过default_factory生成独立字典实例 headers: dict = field(default_factory=lambda: { 'X-ApiKeys': 'accessKey=xxxxxxx;secretKey=xxxxx', 'Content-Type': 'application/json' }) # main方法缩进归入类内部 def main(self): print(self.__host, self.__user, self.__password, self.__database) if __name__ == "__main__": app = Application() app.main()
补充说明
所有可变类型的默认值都遵循这个规则,不要直接给default参数赋值可变对象:
- 空列表默认值用
field(default_factory=list) - 空集合默认值用
field(default_factory=set) - 自定义类的实例默认值也可以通过
default_factory=你的类名实现,每次实例化都会生成新的独立对象
内容的提问来源于stack exchange,提问作者robotiaga
相关产品推荐
相关产品推荐

