问题:Python“扩展”字典
扩展词典与另一本词典的最佳方法是什么?例如:
>>> a = { "a" : 1, "b" : 2 }
>>> b = { "c" : 3, "d" : 4 }
>>> a
{'a': 1, 'b': 2}
>>> b
{'c': 3, 'd': 4}
我正在寻找任何操作来获得此避免for
循环:
{ "a" : 1, "b" : 2, "c" : 3, "d" : 4 }
我希望做这样的事情:
a.extend(b) # This does not work
回答 0
a.update(b)
回答 1
这个封闭的问题中的一颗美丽的宝石:
“单一方式”,既不改变输入命令,也不改变
basket = dict(basket_one, **basket_two)
了解什么是**basket_two
(在**
)指这里。
如果发生冲突,来自的项目basket_two
将覆盖来自的项目basket_one
。就像一线书一样,这是很容易理解和透明的,并且我不反对在任何时候都可以方便地使用由其他两种方法混合而成的字典(实际上,任何理解它的读者都会得到很好的服务)顺便这促使他或她对学习dict
和**
形式;-)。因此,例如,使用如下:
x = mungesomedict(dict(adict, **anotherdict))
在我的代码中相当频繁地出现。
最初由Alex Martelli提交
注意:在Python 3中,只有在basket_two中的每个键都是a的情况下,这才起作用string
。
回答 2
您是否尝试过将字典理解与字典映射一起使用:
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}
# use the merging operator |
c = a | b
# c = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
回答 3
a.update(b)
将键和值从b添加到a,如果键已经存在,则覆盖。
回答 4
正如其他人提到的那样,a.update(b)
对于某些命令而言a
,b
它将达到您在问题中所要求的结果。但是,我想指出的是,我多次看到extend
映射/设置对象的方法希望在语法中a.extend(b)
,a
的值不应被b
的值覆盖。a.update(b)
会覆盖a
的值,因此不是的理想选择extend
。
请注意,某些语言将这种方法称为defaults
或inject
,因为可以将其视为将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提出的巧妙想法,它使用的无副作用dict
构造函数extend
。
回答 5
您还可以使用python 3.3中引入的python的collections.Chainmap。
from collections import Chainmap
c = Chainmap(a, b)
c['a'] # returns 1
根据您的用例,这有一些可能的优点。这里将对它们进行更详细的说明,但我将做一个简要概述:
- 链图仅使用词典的视图,因此实际上没有数据被复制。这样可以加快链接速度(但查找速度较慢)
- 实际上没有键被覆盖,因此,如有必要,您可以知道数据是来自a还是来自b。
这主要使其对于诸如配置字典之类的事情有用。
回答 6
如果您需要将其作为Class,则可以使用dict扩展它并使用update方法:
Class a(dict):
# some stuff
self.update(b)