如何在冻结dataclass初始化时添加动态生成的属性
解决方案
对于冻结的dataclass,你不能直接在__post_init__中赋值属性,也不能用name.lower()作为默认值(类定义阶段name并非实例属性,会引发NameError),以下是两种可行的实现方式:
方法1:利用object.__setattr__在__post_init__中赋值
冻结dataclass重写了__setattr__方法阻止修改,但可以直接调用父类object.__setattr__来绕过限制,实现和第一个类一致的结构:
from dataclasses import dataclass, field from typing import Optional @dataclass(frozen=True) class SecondClass: name: str code: Optional[str] = field(init=False) def __post_init__(self): # 绕过冻结类的赋值限制,初始化code属性 object.__setattr__(self, 'code', self.name.lower())
这种方式会在实例初始化时就生成code属性,作为实例的固定字段存在,和FirstClass的行为保持一致。
方法2:使用cached_property生成缓存属性
如果你的核心需求是缓存计算结果,可以用Python 3.8+提供的functools.cached_property,它会自动缓存第一次计算的结果,后续访问直接读取缓存,无需额外定义字段:
from dataclasses import dataclass from functools import cached_property @dataclass(frozen=True) class SecondClass: name: str @cached_property def code(self) -> str: return self.name.lower()
这种方式更轻量,code会在第一次访问时生成并缓存,适合数据量大、读取成本高的场景,同时完全符合冻结类的只读特性。
内容的提问来源于stack exchange,提问作者brightstar2100
相关产品推荐
相关产品推荐

