为何无法为attrs冻结类对象添加属性?附代码示例及异常分析
嘿,这个问题的核心在于attrs对冻结类的默认__slots__行为,咱们一步步来理清楚:
为什么冻结模式下会报错?
当你给类加上@attrs.define(frozen=True)时,attrs会默认开启slots=True(这是冻结类的默认配置,目的是更早捕获错误、节省内存)。
因为你的类A没有定义任何attrs字段(比如field: int这种格式的声明),所以attrs会自动生成一个空的__slots__。而Python中,一旦类有__slots__,实例就只能拥有__slots__里列出的属性——哪怕你用object.__setattr__这种绕过普通__setattr__的方式,也没法给实例添加不在__slots__里的新属性。
这就是为什么你调用A()后访问field会报错:实际上object.__setattr__根本没成功把field添加到实例上,__slots__的限制直接阻止了这个操作。
而当你去掉frozen=True时,attrs默认会把slots设为False,这时候实例使用普通的__dict__来存储属性,你用object.__setattr__自然能成功添加新属性。
怎么解决这个问题?
有两种常用的办法:
显式定义
field为attrs字段
把field声明为类的字段,让它被包含到自动生成的__slots__里:import attrs @attrs.define(frozen=True) class A: field: int = attrs.field(init=False) # 标记为不需要自动生成初始化参数 def __init__(self): object.__setattr__(self, "field", 1) A() # 正常运行关闭slots功能
在装饰器里手动指定slots=False,这样attrs就不会生成__slots__,实例可以自由添加属性:import attrs @attrs.define(frozen=True, slots=False) class A: def __init__(self): object.__setattr__(self, "field", 1) A() # 正常运行
内容的提问来源于stack exchange,提问作者HerpDerpington
相关产品推荐
相关产品推荐

