如何递归遍历嵌套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
相关产品推荐
相关产品推荐

