这是一个与提供的解决方案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'如何继续获得更多嵌套字典?对不起,如果没有意义,我不明白这是如何运作的。
感谢您的帮助!
答案 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
一开始,original
和d
是同一个对象。将此处的名称视为纸质标签,将其值视为气球。标签用绳子系在气球上。在上面的示例中,d
和original
标签都绑定到同一个字典气球。
当我们输入for key in keys
循环时,d[key]
查找成功,val
与d['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中,您可以修改函数中的可变对象,但不能更改外部名称引用的对象。