Python“extend"一本字典

在避免使用for循环的情况下,用一个字典扩展另一个字典的最佳方法是什么?例如:

>>> a = { "a" : 1, "b" : 2 }
>>> b = { "c" : 3, "d" : 4 }
>>> a
{'a': 1, 'b': 2}
>>> b
{'c': 3, 'd': 4}

结果:

{ "a" : 1, "b" : 2, "c" : 3, "d" : 4 }

喜欢的东西:

a.extend(b)  # This does not work
397711 次浏览
a.update(b)

将添加键和值从b一个,覆盖如果已经有一个键的值。

这个封闭式问题中一个美丽的宝石:

“联机方式”,改变任何输入字典,是

basket = dict(basket_one, **basket_two)

学习#EYZ0 (**)表示这里

在冲突的情况下,来自basket_two的项目将覆盖来自basket_one的项目。作为一行程序,这是相当可读的和透明的,而且我对任何时候使用它都没有内疚,因为它是其他两种字典的混合(任何有理解困难的读者实际上都会很好地通过这种方式提示他或她学习dict**形式;-)。所以,例如,使用像:

x = mungesomedict(dict(adict, **anotherdict))

在我的代码中相当频繁地出现。

最初由马特利亚历克斯提交

在Python 3中,只有当basket_two中的每个键都是string时,这才有效。

正如其他人所提到的,a.update(b)对于一些字典ab将达到你在问题中要求的结果。然而,我想指出的是,我多次看到extend方法映射/设置对象希望在语法a.extend(b)中,a的值不应该被b的值覆盖。a.update(b)覆盖了a的值,因此对于extend不是一个好的选择。

注意,有些语言将此方法称为defaultsinject,因为它可以被认为是将b的值(可能是一组默认值)注入到字典中而不覆盖可能已经存在的值的一种方式。

当然,您可以简单地注意到a.extend(b)几乎与b.update(a); a=b相同。要删除赋值,你可以这样做:

def extend(a,b):
"""Create a new dictionary with a's properties extended by b,
without overwriting.


>>> extend({'a':1,'b':2},{'b':3,'c':4})
{'a': 1, 'c': 4, 'b': 2}
"""
return dict(b,**a)

感谢Tom Leys为extend使用副作用较小的dict构造函数的聪明想法。

你试过使用字典映射的字典理解吗?

a = {'a': 1, 'b': 2}
b = {'c': 3, 'd': 4}


c = {**a, **b}
# c = {"a": 1, "b": 2, "c": 3, "d": 4}

另一种方法是使用dict(iterable, **kwarg)

c = dict(a, **b)
# c = {'a': 1, 'b': 2, 'c': 3, 'd': 4}

在Python 3.9中,您可以使用联合|操作符添加两个字典

# use the merging operator |
c = a | b
# c = {'a': 1, 'b': 2, 'c': 3, 'd': 4}

你也可以使用python的集合。Chainmap,它是在python 3.3中引入的。

from collections import Chainmap
c = Chainmap(a, b)
c['a'] # returns 1

这有一些可能的优势,这取决于您的用例。它们在在这里中有更详细的解释,但我将给出简要的概述:

  • 链图只使用字典的视图,因此实际上不会复制任何数据。这将导致更快的链接(但更慢的查找)
  • 没有键实际上被覆盖,因此,如果有必要,您可以知道数据是来自a还是b。

这主要使它对配置字典之类的事情有用。

注意,Python 3.9引入了更简单的语法(结合运营商):

d1 = {'a': 1}
d2 = {'b': 2}


extended_dict = d1 | d2
>> {'a':1, 'b': 2}

注意:如果第一个字典和第二个字典共享键,位置很重要!

d1 = {'b': 1}
d2 = {'b': 2}
d1 | d2
>> {'b': 2}

相关PEP

就效率而言,与更新方法相比,使用解包操作似乎更快。

这是我做的一个测试的图片: # EYZ0 < / p >