栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

嵌套字典中的Python数据类

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

嵌套字典中的Python数据类

下面是它使用

asdict
的内部递归帮助器功能的CPython实现
_asdict_inner

# Source: https://github.com/python/cpython/blob/master/Lib/dataclasses.pydef _asdict_inner(obj, dict_factory):    if _is_dataclass_instance(obj):        result = []        for f in fields(obj): value = _asdict_inner(getattr(obj, f.name), dict_factory) result.append((f.name, value))        return dict_factory(result)    elif isinstance(obj, tuple) and hasattr(obj, '_fields'):        # [large block of author comments]        return type(obj)(*[_asdict_inner(v, dict_factory) for v in obj])    elif isinstance(obj, (list, tuple)):        # [ditto]        return type(obj)(_asdict_inner(v, dict_factory) for v in obj)    elif isinstance(obj, dict):        return type(obj)((_asdict_inner(k, dict_factory),    _asdict_inner(v, dict_factory))   for k, v in obj.items())    else:        return copy.deepcopy(obj)

asdict
只需在
dict_factory=dict
默认情况下使用一些断言调用上述方法即可。

如注释中所述,如何调整它以创建带有所需类型标记的输出字典?


1.添加类型信息

我的尝试涉及创建一个自定义继承自的返回包装器

dict

class TypeDict(dict):    def __init__(self, t, *args, **kwargs):        super(TypeDict, self).__init__(*args, **kwargs)        if not isinstance(t, type): raise TypeError("t must be a type")        self._type = t    @property    def type(self):        return self._type

综观原代码,只有第一条需要进行修改,以使用该包装,与其他条款只处理 集装箱

dataclass
-es:

# only use dict for now; easy to add back laterdef _todict_inner(obj):    if is_dataclass_instance(obj):        result = []        for f in fields(obj): value = _todict_inner(getattr(obj, f.name)) result.append((f.name, value))        return TypeDict(type(obj), result)    elif isinstance(obj, tuple) and hasattr(obj, '_fields'):        return type(obj)(*[_todict_inner(v) for v in obj])    elif isinstance(obj, (list, tuple)):        return type(obj)(_todict_inner(v) for v in obj)    elif isinstance(obj, dict):        return type(obj)((_todict_inner(k), _todict_inner(v))   for k, v in obj.items())    else:        return copy.deepcopy(obj)

进口:

from dataclasses import dataclass, fields, is_dataclass# thanks to Patrick Haughfrom typing import *# deepcopy import copy

使用的功能:

# copy of the internal function _is_dataclass_instancedef is_dataclass_instance(obj):    return is_dataclass(obj) and not is_dataclass(obj.type)# the adapted version of asdictdef todict(obj):    if not is_dataclass_instance(obj):         raise TypeError("todict() should be called on dataclass instances")    return _todict_inner(obj)

使用示例数据类进行测试:

c = C([Point(0, 0), Point(10, 4)])print(c)cd = todict(c)print(cd)# {'mylist': [{'x': 0, 'y': 0}, {'x': 10, 'y': 4}]}print(cd.type)# <class '__main__.C'>

结果符合预期。


2.转换回

dataclass

所使用的递归例程

asdict
可以用于反向过程,但需要进行一些相对较小的更改:

def _fromdict_inner(obj):    # reconstruct the dataclass using the type tag    if is_dataclass_dict(obj):        result = {}        for name, data in obj.items(): result[name] = _fromdict_inner(data)        return obj.type(**result)    # exactly the same as before (without the tuple clause)    elif isinstance(obj, (list, tuple)):        return type(obj)(_fromdict_inner(v) for v in obj)    elif isinstance(obj, dict):        return type(obj)((_fromdict_inner(k), _fromdict_inner(v))   for k, v in obj.items())    else:        return copy.deepcopy(obj)

使用的功能:

def is_dataclass_dict(obj):    return isinstance(obj, TypeDict)def fromdict(obj):    if not is_dataclass_dict(obj):        raise TypeError("fromdict() should be called on TypeDict instances")    return _fromdict_inner(obj)

测试:

c = C([Point(0, 0), Point(10, 4)])cd = todict(c)cf = fromdict(cd)print(c)# C(mylist=[Point(x=0, y=0), Point(x=10, y=4)])print(cf)# C(mylist=[Point(x=0, y=0), Point(x=10, y=4)])

再次如预期。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/626466.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号