Python使用列表中的项嵌套dicts

时间:2013-09-08 23:20:39

标签: python dictionary nested

这是一个与提供的解决方案here相关的问题,它涉及以下代码作为解决方案:

from collections import MutableMapping

def set_value(d, keys, newkey, newvalue, default_factory=dict):
    """
    Equivalent to `reduce(dict.get, keys, d)[newkey] = newvalue`
    if all `keys` exists and corresponding values are of correct type
    """
    for key in keys:
        try:
            val = d[key]
        except KeyError:
            val = d[key] = default_factory()
        else:
            if not isinstance(val, MutableMapping):
                val = d[key] = default_factory()
        d = val
    d[newkey] = newvalue

我希望有人可以解释为什么这段代码有效。我很困惑传递的词典“d”在d = val的情况下不会被不断覆盖。如果没有索引到下一个节点,dict'd'如何继续获得更多嵌套字典?对不起,如果没有意义,我不明白这是如何运作的。

感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

d 反弹;变量更新为指向每个循环中的val

对于key中的每个keys,找到密钥(val = d[key]成功)或default_factory()用于为该密钥创建新值。

如果找到密钥但该值不是MutableMapping类型,则找到的值将替换为新的default_factory()结果。

确定此级别的新值后,d会被告知忘记旧字典并指向新字典。

重新绑定更改旧值。它只是停止引用那个旧值。

让我们用一个简单的例子:

>>> d = {'foo': {}}
>>> keys = ['foo']
>>> newkey = 'bar'
>>> newval = 'eggs'
>>> original = d

一开始,originald是同一个对象。将此处的名称视为纸质标签,将其值视为气球。标签用绳子系在气球上。在上面的示例中,doriginal标签绑定到同一个字典气球。

当我们输入for key in keys循环时,d[key]查找成功,vald['foo']的结果相关联,这是一个空字典:

>>> key = keys[0]
>>> key
'foo'
>>> val = d[key]
>>> val
{}

这是一个常规的Python字典,isinstance(val, MutableMapping)True。下一行将<{1}}标签重新到该字典。该字符串只是原始字典中的解开,现在附加到同一个气球d并绑定到:

val

原始字典没有被重新绑定改变!

用完密钥(>>> d = val >>> d {} >>> original {'foo': {}} >>> d is val True >>> d is original False 中只有一个),然后下一部分将keys分配给newval

d[newkey]

但是,>>> d[newkey] = newval >>> d {'bar': 'eggs'} 并不是此词典气球附带的唯一标签。字典本身包含键和值,两者都是与气球绑定的标签! d标签仍然与外部字典气球绑定,并且它具有original键关联值,该值与嵌套字典相关联,而这是我们刚刚更改的嵌套字典:

foo

该算法仅通过字符串跟随标签到新词典。

使用更复杂的键组合只意味着要遵循更多的字符串,可能需要额外的字典才能被绑定。

答案 1 :(得分:1)

我认为你的问题归结为:

为什么d[newkey] = newvalue会修改对象,而d = var对对象没有任何作用?

在Python中,您可以修改函数中的可变对象,但不能更改外部名称引用的对象。