首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从dict构造一个嵌套的defaultdict?

从dict构造一个嵌套的defaultdict?
EN

Stack Overflow用户
提问于 2018-12-28 16:17:30
回答 3查看 557关注 0票数 2

是否可以将讨论的here方法扩展到嵌套的defaultdict?

编辑:

根据注释,缺省值将从原始None更新为lambda: None。但是,以下内容仍未按预期工作:

代码语言:javascript
复制
from collections import defaultdict
dd = defaultdict(lambda: None, {"a":1,"b":{"c":3}})

dd["b"]["e"]会引发一个KeyError,而不是返回None。

如何将所有嵌套的dict转换为defaultdict?

EN

回答 3

Stack Overflow用户

发布于 2018-12-28 16:44:55

你可以这样做:

代码语言:javascript
复制
from collections import defaultdict


def to_none(d, factory):
    result = defaultdict(factory)
    for key, value in d.items():
        if isinstance(value, dict):
            result[key] = to_none(value, factory)
        else:
            result[key] = value
    return result


d = {"a": 1, "b": {"c": 3}}

dd = to_none(d, lambda: None)

print(dd['a'])
print(dd['xxx'])
print(dd['b']['c'])
print(dd['b']['e'])

输出

代码语言:javascript
复制
1
None
3
None
票数 2
EN

Stack Overflow用户

发布于 2018-12-28 16:45:55

collections.defaultdict不是实现这一目的的理想工具。若要将None指定为嵌套字典的默认值,只需在没有找到任何级别的键时使用iterate your dictionary recursively并使用dict.get返回None

代码语言:javascript
复制
from functools import reduce

def get_from_dict(dataDict, mapList):
    """Iterate nested dictionary"""
    return reduce(dict.get, mapList, dataDict)

d = {"a": 1, "b": {"c": 3}}

get_from_dict(d, ['b', 'e'])  # None
get_from_dict(d, ['b', 'c'])  # 3
票数 1
EN

Stack Overflow用户

发布于 2019-01-11 06:03:14

代码语言:javascript
复制
def _sub_getitem(self, k):
    try:
        # sub.__class__.__bases__[0]
        real_val = self.__class__.mro()[-2].__getitem__(self, k)
        val = '' if real_val is None else real_val
    except Exception:
        val = ''
        real_val = None
    # isinstance(Avoid,dict)也是true,会一直递归死
    if type(val) in (dict, list, str, tuple):
        val = type('Avoid', (type(val),), {'__getitem__': _sub_getitem, 'pop': _sub_pop})(val)
        # 重新赋值当前字典键为返回值,当对其赋值时可回溯
        if all([real_val is not None, isinstance(self, (dict, list)), type(k) is not slice]):
            self[k] = val
    return val


def _sub_pop(self, k=-1):
    try:
        val = self.__class__.mro()[-2].pop(self, k)
        val = '' if val is None else val
    except Exception:
        val = ''
    if type(val) in (dict, list, str, tuple):
        val = type('Avoid', (type(val),), {'__getitem__': _sub_getitem, 'pop': _sub_pop})(val)
    return val


class DefaultDict(dict):
    def __getitem__(self, k):
        return _sub_getitem(self, k)

    def pop(self, k):
        return _sub_pop(self, k)

In[8]: d=DefaultDict({'balabala':"dddddd"})
In[9]: d['a']['b']['c']['d']
Out[9]: ''
In[10]: d['a']="ggggggg"
In[11]: d['a']
Out[11]: 'ggggggg'
In[12]: d['a']['pp']
Out[12]: ''

不要再犯错误。不管嵌套了多少级别。弹出没有错误,也可以更改为任何值,如果你想。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53961347

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档