使用Dataclasses与__slots__时触发ValueError:'b'与类变量冲突
Python 3.9 dataclass 与 slots 冲突问题解决
问题背景
在Python 3.9.2环境下使用dataclass时触发ValueError: 'b' in __slots__ conflicts with class variable错误,已知Python 3.10的dataclasses支持slots=True参数,但当前无法升级版本。
错误栈信息:
Traceback (most recent call last):
File "/home/user/dc.py", line 6, in
class Foo:
ValueError: 'b' in slots conflicts with class variable
代码逻辑:成员b并非__init__的直接参数,而是基于参数ccc计算得到的,因此设置@dataclass(init=False)自定义__init__方法,并将b设为field(init=False)避免dataclass自动初始化,但仍出现冲突错误。
原测试代码:
#!/usr/bin/env python3 from dataclasses import dataclass, field @dataclass(init=False) class Foo: __slots__ = ('a', 'b') a: int b: list[str] = field(init=False) def __init__(self, a, ccc): self.a = a # b = _some_fancy_modifications(ccc) self.b = b if __name__ == '__main__': f = Foo(1, list('bar'))
问题原因
Python 3.9的dataclass实现中,当为字段b设置field(init=False)时,dataclass会自动在类级别创建一个同名的类变量作为默认值占位符。而__slots__的特性是禁止类级别存在与插槽同名的类变量,两者规则冲突,因此触发报错。
解决方案
去掉b的field(init=False)赋值,仅保留类型注解即可:
#!/usr/bin/env python3 from dataclasses import dataclass, field @dataclass(init=False) class Foo: __slots__ = ('a', 'b') a: int b: list[str] # 仅保留类型注解,移除field(init=False) def __init__(self, a, ccc): self.a = a # 示例计算逻辑,替换为实际业务代码 b = ccc.copy() self.b = b if __name__ == '__main__': f = Foo(1, list('bar')) print(f.a, f.b)
补充说明
- 由于已经设置
@dataclass(init=False),dataclass不会自动生成初始化逻辑,因此无需用field(init=False)来排除字段。 __slots__的核心作用是限制实例可拥有的属性,同时会禁止类级别存在同名类变量,只要类中不定义同名类变量,即可与dataclass兼容使用。
内容的提问来源于stack exchange,提问作者buhtz
相关产品推荐
相关产品推荐

