这是一个与提供的解决方案相关的问题 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 处不断被覆盖。字典“d”如何不断获取进一步嵌套的字典而不索引到下一个节点?抱歉,如果这没有意义,我不明白这是如何工作的。
感谢您的帮助!
最佳答案
d
正在反弹;在每个循环中变量都会更新为指向 val
。
对于 keys
中的每个 key
,要么找到该键(val = d[key]
成功),要么找到 default_factory ()
用于为该键创建新值。
如果找到键但值不是 MutableMapping
类型,则找到的值将替换为新的 default_factory()
结果。
一旦确定了该级别的新值,d
就会被告知忘记旧字典并指向新字典。
重新绑定(bind)不会更改旧值。它只是停止引用那个旧值。
让我们用一个简单的例子:
>>> d = {'foo': {}}
>>> keys = ['foo']
>>> newkey = 'bar'
>>> newval = 'eggs'
>>> original = d
一开始,original
和 d
是同一个对象。将此处的名称视为纸质标签,将其值视为气球。标签用绳子绑在气球上。在上面的示例中,d
和 original
标签都绑定(bind)到同一个字典气球。
当我们进入 for key in keys
循环时,d[key]
查找成功,并且 val
与 的结果绑定(bind)在一起code>d['foo']
,一个空字典:
>>> key = keys[0]
>>> key
'foo'
>>> val = d[key]
>>> val
{}
这是一个常规的 Python 字典,并且 isinstance(val, MutableMapping)
为 True
。下一行将 d
标签重新绑定(bind)到该字典。该字符串只是从原始字典解开,现在附加到同一个气球 val
绑定(bind)到:
>>> d = val
>>> d
{}
>>> original
{'foo': {}}
>>> d is val
True
>>> d is original
False
原始字典并未因重新绑定(bind)而改变!
用完 key 后(keys
中只有一个),下一部分将 newval
分配给 d[newkey]
:
>>> d[newkey] = newval
>>> d
{'bar': 'eggs'}
但是,d
并不是附加到此字典气球的唯一标签。字典本身包含键和值,这两者都是与气球绑定(bind)的标签! original
标签仍然绑定(bind)到外部字典气球,并且它有一个 foo
键关联值,该值绑定(bind)到一个嵌套字典,我们就是这个嵌套字典。刚刚改变:
>>> original
{'foo': {'bar': 'eggs'}}
该算法只是通过字符串沿着标签跟踪新的字典。
使用更复杂的组合键仅仅意味着要遵循更多的字符串,也许还需要绑定(bind)一个额外的字典。
关于Python 嵌套字典使用列表中的项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18689623/