如何在冻结的dataclass中初始化列表字段的副本?
解决冻结Dataclass中列表字段创建副本的问题
针对你遇到的冻结dataclass无法在__post_init__中修改字段,同时需要为other列表创建副本的问题,有两种简洁的解决方式:
方法一:使用field的converter参数(Python 3.10+)
从Python 3.10开始,dataclasses.field支持converter参数,可以在字段初始化时自动转换传入的值。直接给other字段添加转换器,生成列表副本:
from dataclasses import dataclass, field from typing import List @dataclass(frozen=True, eq=True) class Node: name: str rate: int other: List[str] = field(compare=False, converter=lambda lst: lst.copy())
这样每次传入other参数时,转换器会自动创建列表副本,既不用重写__init__,也不会触发冻结实例的赋值限制。
方法二:重写__init__并使用object.__setattr__(兼容低版本Python)
如果你的Python版本低于3.10,没有converter参数,可以重写__init__,借助object.__setattr__绕过冻结实例的赋值限制,手动创建列表副本:
from dataclasses import dataclass, field from typing import List @dataclass(frozen=True, eq=True) class Node: name: str rate: int other: List[str] = field(compare=False) def __init__(self, name: str, rate: int, other: List[str]): # 先创建传入列表的副本 other_copy = other.copy() # 用object.__setattr__给冻结实例赋值,避免触发不可变限制 object.__setattr__(self, 'name', name) object.__setattr__(self, 'rate', rate) object.__setattr__(self, 'other', other_copy)
这种方式只需要简单重写__init__,不用手动处理所有dataclass的初始化逻辑,符合dataclass的使用初衷。
两种方法都能保证other字段是独立的副本,修改它不会影响原始解析结果。
内容的提问来源于stack exchange,提问作者Kezif Garbian
相关产品推荐
相关产品推荐

