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

如何递归遍历嵌套dataclass并转字典,且保留指定dataclass类型?

自定义dataclass转字典:保留指定类实例

方法一:通过函数参数标记不展开的类

给custom_asdict函数传入需要保留实例的类列表,遍历dataclass字段时判断类型,符合条件就跳过展开,直接保留实例。

from dataclasses import dataclass, is_dataclass

def custom_asdict(obj, exclude_classes=None):
    exclude_classes = exclude_classes or ()
    if not is_dataclass(obj):
        return obj
    result = {}
    for field_name, field_val in obj.__dict__.items():
        if isinstance(field_val, exclude_classes):
            result[field_name] = field_val
        else:
            result[field_name] = custom_asdict(field_val, exclude_classes)
    return result

# 测试代码
@dataclass
class C:
    x: int = 1

@dataclass
class B:
    c: C = C()

@dataclass
class A:
    b: B = B()

print(custom_asdict(A(), exclude_classes=(C,)))
# 输出: {'b': {'c': C(x=1)}}

方法二:通过dataclass装饰器元数据标记

给需要保留实例的类添加元数据标记,custom_asdict函数自动识别该标记,无需每次传参。

from dataclasses import dataclass, fields, is_dataclass

def custom_asdict(obj):
    if not is_dataclass(obj):
        return obj
    result = {}
    for field_info in fields(obj):
        field_val = getattr(obj, field_info.name)
        if is_dataclass(field_val) and field_val.__dataclass_metadata__.get("keep_instance", False):
            result[field_info.name] = field_val
        else:
            result[field_info.name] = custom_asdict(field_val)
    return result

# 测试代码
@dataclass(metadata={"keep_instance": True})
class C:
    x: int = 1

@dataclass
class B:
    c: C = C()

@dataclass
class A:
    b: B = B()

print(custom_asdict(A()))
# 输出: {'b': {'c': C(x=1)}}

两种方法都能适配复杂嵌套结构:方法一更灵活,可临时指定需要保留实例的类;方法二更直观,在类定义阶段就标记好规则,可根据实际场景选择使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 11:25:30