Python 字典的“扩展”
- 2025-04-15 09:20:00
- admin 原创
- 71
问题描述:
在避免使用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
解决方案 1:
a.update(b)
最新的 Python 标准库文档
解决方案 2:
这个封闭式问题中有一颗美丽的宝石:
“单行方式”,不改变任何输入指令,是
basket = dict(basket_one, **basket_two)
在这里了解**basket_two
(the **
)的含义。
如果发生冲突,来自 的项目basket_two
将覆盖来自 的项目basket_one
。就单行代码而言,这非常易读且透明,每当需要使用由另外两个项目混合而成的字典时,我都会毫不犹豫地使用它(任何难以理解它的读者实际上都会受益于这种方式,因为它会促使他或她学习dict
和**
形式 ;-)。例如,像这样的用法:
x = mungesomedict(dict(adict, **anotherdict))
在我的代码中出现的频率相当高。
最初由Alex Martelli提交
注意:在 Python 3 中,仅当basket_two 中的每个键都是 时,此方法才有效string
。
解决方案 3:
您是否尝试过使用字典理解和字典映射:
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 中,你可以使用 union | 运算符添加两个字典
# use the merging operator |
c = a | b
# c = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
解决方案 4:
a.update(b)
将从b向a添加键和值,如果键已经有值则覆盖。
解决方案 5:
请注意,自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
解决方案 6:
正如其他人提到的,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
。
解决方案 7:
您还可以使用python 3.3 中引入的python 的collections.ChainMap 。
from collections import ChainMap
c = ChainMap(a, b)
c['a'] # returns 1
根据你的用例,这可能有几个优点。这里有更详细的解释,但我先简单概述一下:
链式映射仅使用字典的视图,因此实际上不会复制任何数据。这会导致链接速度更快(但查找速度更慢)。
实际上没有覆盖任何键,因此,如有必要,您知道数据来自 a 还是 b。
这主要使其对于配置字典之类的东西有用。
解决方案 8:
从效率上来说,使用解包操作似乎比更新方法更快。
这是我做的测试的图片:
扫码咨询,免费领取项目管理大礼包!