我想将两个词典融入一个新的词典。

x = {'a': 1, 'b': 2}
y = {'b': 3, 'c': 4}
z = merge(x, y)

>>> z
{'a': 1, 'b': 3, 'c': 4}

每当两个字典中都有一个关键 k 时,只应保留 y(k) 的值。


当前回答

在Python 3.8发布时,将有一个新的选项(计划于2019年10月20日),感谢PEP 572:分配表达式。 新的分配表达式操作员:= 允许您分配副本的结果,并且仍然使用它来呼叫更新,留下组合代码一个单一表达式,而不是两个陈述,改变:

newdict = dict1.copy()
newdict.update(dict2)

到:

(newdict := dict1.copy()).update(dict2)

(newdict := dict1.copy()).update(dict2) or newdict

newdict = {**dict1, **dict2}

脱包方法更清晰(对于任何人都知道一般的脱包,首先,你应该),不需要一个名字的结果(因此,它是更紧密的,当构建一个暂时的,即时转移到一个功能或包含在一个名单 / 双字或类似),并且几乎肯定更快,也是(在CPython上)相当于:

newdict = {}
newdict.update(dict1)
newdict.update(dict2)

它也更可扩展,因为结合三个法则是显而易见的:

 newdict = {**dict1, **dict2, **dict3}

 (newdict := dict1.copy()).update(dict2), newdict.update(dict3)

或沒有暫時的九個,但以真實的測試,每個九個結果:

 (newdict := dict1.copy()).update(dict2) or newdict.update(dict3)

其他回答

这个问题被标签为Python-3x,但考虑到这是一个相对较新的补充,并且最受欢迎的,接受的答案与Python 2.x解决方案广泛处理,我敢添加一个线条,引用一个令人兴奋的功能的Python 2.x列表理解,即名字泄漏。

$ python2
Python 2.7.13 (default, Jan 19 2017, 14:48:08) 
[GCC 6.3.0 20170118] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> [z.update(d) for z in [{}] for d in (x, y)]
[None, None]
>>> z
{'a': 1, 'c': 11, 'b': 10}
>>> ...

我很高兴说上面的内容不再在任何Python 3版本上工作。

如果你認為Lambdas是壞的,那麼不要再閱讀。 如要求,你可以用一個表達寫下快速和記憶效益的解決方案:

x = {'a':1, 'b':2}
y = {'b':10, 'c':11}
z = (lambda a, b: (lambda a_copy: a_copy.update(b) or a_copy)(a.copy()))(x, y)
print z
{'a': 1, 'c': 11, 'b': 10}
print x
{'a': 1, 'b': 2}

如上所述,使用两行或写一个函数可能是一个更好的方式去。

一个方法是深合的. 使用操作员在 3.9+ 用于使用案例的 dict 新是默认设置的组合,而 dict 现有是使用的现有设置的组合. 我的目标是融入任何添加设置从新没有过写现有设置在现有. 我相信这个重复的实施将允许一个升级一个 dict 与新的值从另一个 dict。

def merge_dict_recursive(new: dict, existing: dict):
    merged = new | existing

    for k, v in merged.items():
        if isinstance(v, dict):
            if k not in existing:
                # The key is not in existing dict at all, so add entire value
                existing[k] = new[k]

            merged[k] = merge_dict_recursive(new[k], existing[k])
    return merged

示例测试数据:

new
{'dashboard': True,
 'depth': {'a': 1, 'b': 22222, 'c': {'d': {'e': 69}}},
 'intro': 'this is the dashboard',
 'newkey': False,
 'show_closed_sessions': False,
 'version': None,
 'visible_sessions_limit': 9999}
existing
{'dashboard': True,
 'depth': {'a': 5},
 'intro': 'this is the dashboard',
 'newkey': True,
 'show_closed_sessions': False,
 'version': '2021-08-22 12:00:30.531038+00:00'}
merged
{'dashboard': True,
 'depth': {'a': 5, 'b': 22222, 'c': {'d': {'e': 69}}},
 'intro': 'this is the dashboard',
 'newkey': True,
 'show_closed_sessions': False,
 'version': '2021-08-22 12:00:30.531038+00:00',
 'visible_sessions_limit': 9999}

另一个,更细致的选择:

z = dict(x, **y)

注意:这已成为一个受欢迎的答案,但重要的是要指出的是,如果 y 有任何不紧密的密钥,事实上,这完全是CPython实施细节的滥用,并且它不在Python 3或PyPy,IronPython,或Jython工作。

虽然这个问题已经被回答了几次,但这个问题的简单解决方案尚未列出。

x = {'a':1, 'b': 2}
y = {'b':10, 'c': 11}
z4 = {}
z4.update(x)
z4.update(y)

它像 z0 和 Z2 上述那样快,但很容易理解和改变。