You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python Dataclass中让字典字段实现深拷贝且无需post_init?

Python Dataclass字典字段实现深拷贝(无需post_init)

方案1:利用field的converter参数实现自动深拷贝

Python 3.10+的dataclasses.field提供了converter参数,可以在字段赋值前自动对传入的参数进行转换,刚好适合用来做深拷贝,完全不需要依赖__post_init__。

代码示例:

from dataclasses import dataclass, field
from typing import Dict
import copy


@dataclass
class ClassWithDict:
    the_dict: Dict = field(
        default_factory=dict,
        kw_only=True,
        converter=copy.deepcopy
    )


toto = {"toto": "tata"}
the_class = ClassWithDict(the_dict=toto)

assert toto == the_class.the_dict
assert toto is not the_class.the_dict  # 现在结果为TRUE

# 验证深拷贝效果:修改原字典不会影响类内的字典
toto["extra"] = "value"
assert the_class.the_dict.get("extra") is None  # 断言成立

方案2:自定义默认工厂+转换器(覆盖默认值与传入值场景)

如果需要确保默认空字典和传入外部字典都能保持独立的深拷贝(比如默认值是非空字典时),可以结合default_factory和converter:

from dataclasses import dataclass, field
from typing import Dict
import copy


@dataclass
class ClassWithDict:
    the_dict: Dict = field(
        default_factory=lambda: copy.deepcopy({"default": "val"}),
        kw_only=True,
        converter=copy.deepcopy
    )


# 测试默认值独立性
inst1 = ClassWithDict()
inst1.the_dict["default"] = "modified"
inst2 = ClassWithDict()
assert inst2.the_dict["default"] == "val"  # 两个实例的默认字典相互独立

# 测试传入值深拷贝
external_dict = {"external": "data"}
inst3 = ClassWithDict(the_dict=external_dict)
external_dict["external"] = "changed"
assert inst3.the_dict["external"] == "data"  # 深拷贝生效,不受原字典修改影响

版本兼容提示

如果使用的是Python 3.9及以下版本,converter参数尚未支持,可以自定义描述符类来实现类似逻辑:

from dataclasses import dataclass, field
from typing import Dict
import copy


class DeepCopyDict:
    def __set_name__(self, owner, name):
        self.name = name

    def __get__(self, instance, owner):
        return instance.__dict__.get(self.name, {})

    def __set__(self, instance, value):
        instance.__dict__[self.name] = copy.deepcopy(value)


@dataclass
class ClassWithDict:
    the_dict: Dict = field(default_factory=dict, kw_only=True)
    # 替换字段类型为自定义描述符
    the_dict: Dict = DeepCopyDict()


toto = {"toto": "tata"}
the_class = ClassWithDict(the_dict=toto)
assert toto is not the_class.the_dict  # 结果为TRUE

内容的提问来源于stack exchange,提问作者Milan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 02:10:27