老齐教室

Python3.9中合并字典的新方法

作者:Yong Cui, Ph.D.

翻译:老齐

与本文相关的图书推荐:《跟老齐学Python:轻松入门》


Python3.9,还在研发中,计划今年10月份发布,2月26日,研发团队发布了α版,其中有一个新功能,会关系到所有开发者,那就是两个操作符:||=,分别实现对字典的合并操作。

本文对此给予简要介绍。

字典

Python中的字典,即dict,是一种重要的内置对象类型,它是一种以键值对方式保存数据的容器,因为使用了哈希,使得查询字典中数据时的时间复杂度恒定,这是它美名远播的一个原因。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 创建字典
student = {'name': 'John', 'age': 14}

# 读取值
age = student['age']
# age is 14

# Update 一个值
student['age'] = 15
# student 变成 {'name': 'John', 'age': 15}

# 插入一个键值对
student['score'] = 'A'
# student 变成 {'name': 'John', 'age': 15, 'score': 'A'}

以往合并字典的方法

有时,我们需要将两个字典合并,在Python3.9之前,有几种方法可以实现。假设有两个字典:d1d2,新建一个字典d3,它的值是d1d2的并集。从下面的演示中我们可以看到,如果字典中被合并的字典中有重复的键,例如d2如果是字典d2a那样,就会把d1中同名的键覆盖了。

1
2
3
4
5
6
7
# two dicts to start with
d1 = {'a': 1, 'b': 2}
d2 = {'c': 3, 'd': 4}
d2a = {'a': 10, 'c': 3, 'd': 4}

# target dict
d3 = {'a': 1, 'b': 2, 'c': 3, 'd': 4}

update()方法

第一种方法我们使用字典的update()方法,下面的代码中演示了操作方法。注意,首先要创建d1的拷贝,否则update()会把原字典的值修改了。

1
2
3
4
5
6
7
# create a copy of d1, as update() modifies the dict in-place
d3 = d1.copy()
# d3 is {'a': 1, 'b': 2}

# update the d3 with d2
d3.update(d2)
# d3 now is {'a': 1, 'b': 2, 'c': 3, 'd': 4}

如果字典中有重名的键,我们必须更加谨慎,确定保留哪些值。如下代码所示,作为update()方法的参数d2a中,与d3有重复的键,比如a,此时会遵循“最后一个有效”的原则合并。

1
2
3
4
5
6
7
d3 = d1.copy()
d3.update(d2a)
# d3 now is {'a': 10, 'b': 2, 'c': 3, 'd': 4}
# This is not the way that we want d3 = d2a.copy()
d3.update(d1)
# d3 now is {'a': 1, 'c': 3, 'd': 4, 'b': 2}
# This is the way that we want

解包字典

第二种方法使用字典解包,类似上面的方法,如果有重名的键,依然是“最后一个有效”。

1
2
3
4
5
6
# unpacking
d3 = {**d1, **d2}
# d3 is {'a': 10, 'b': 2, 'c': 3, 'd': 4}
# Not right d3 = {**d2a, **d1}
# d3 is {'a': 1, 'c': 3, 'd': 4, 'b': 2}
# Good

使用dict(iterable, **kwarg)

利用dict(iterable, **kwarg)方法创建一个字典。如果参数iterable是一个字典,就可以创建一个同样键值对的字典,再提供另外一个字典,就可以将这个字典的键值对增加到前面字典中。注意,这个字典如果跟前面字典中有同名的参数,依然是“最后一个有效”。

1
2
3
4
5
d3 = dict(d1, **d2)
# d3 is {'a': 1, 'b': 2, 'c': 3, 'd': 4}
# Good, it's what we wantd3 = dict(d1, **d2a)
# d3 is {'a': 10, 'b': 2, 'c': 3, 'd': 4}
# Not right, 'a' value got replaced

注意,上面的方法只适用于以字符串为键的字典,因为它其实是以关键词传参。如果像下面这样,就会报错了。

1
2
3
4
5
6
>>> dict({'a': 1}, **{2: 3})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: keywords must be strings
>>> dict({'a': 1}, **{'2': 3})
{'a': 1, '2': 3}

合并字典的新方法

在最近发布的Python3.9.0α4中,提供了合并运算符|,用于很方便地实现两个字典的合并,下面给出一个示例。你一定会注意到,如果两个字典中有重名的键,依然是“最后一个有效”,这与前面所看到的没有区别,比如update()方法那样的操作。

1
2
3
4
5
6
# use the merging operator |
d3 = d1 | d2
# d3 is now {'a': 1, 'b': 2, 'c': 3, 'd': 4}
# goodd3 = d1 | d2a
# d3 is now {'a': 10, 'b': 2, 'c': 3, 'd': 4}
# not good

与上述运算符相关的是一个增强版的运算符|=,它的作用是对字典进行原地修改,从本质上讲,与update()一样,以下代码段显示其用法:

1
2
3
4
5
6
7
8
9
10
11
# Create a copy for d1
d3 = d1.copy()

# Use the augmented assignment of the merge operator
d3 |= d2
# d3 now is {'a': 1, 'b': 2, 'c': 3, 'd': 4}
# good

d3 |= d2a
# d3 now is {'a': 10, 'b': 2, 'c': 3, 'd': 4}
# not good

总结

本文展示了Python3.9即将发布的一个关于合并字典的运算符,此外,对asynciomathos模块也有一些更新,迫不及待了吗?10月份Python3.9发布之时,官方文档会有详细说明,敬请查看。

原文链接:https://medium.com/better-programming/dictionary-merging-and-updating-in-python-3-9-4ac67c667ce

搜索技术问答的公众号:老齐教室

在公众号中回复:老齐,可查看所有文章、书籍、课程。

觉得好看,就点赞转发

使用支付宝打赏
使用微信打赏

若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏

关注微信公众号,读文章、听课程,提升技能