10

这样合并Python字典,可以让程序的运行效率提高4倍

 3 years ago
source link: https://blog.csdn.net/nokiaguy/article/details/113533292
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
这样合并Python字典,可以让程序的运行效率提高4倍_李宁的极客世界bgJBm&nku$q$-CSDN博客

摘要:在Python中,合并字典有多种方式,通过内建函数、运算符、自定义函数等,都可以完成合并字典的功能,但这些方式,哪些效率低,哪些效率高呢?本文将对这些合并字典的方式进行逐个深度详解,最后会比较这些方式,看看到底谁是效率之王!

现在提出一个问题:如何用一行代码合并两个Python字典,并返回合并结果。可能很多同学最先想到的是下面的代码:

这段代码没有任何问题,通过update方法可以将x和y合并,但问题是update方法修改了x的值,将合并的结果赋给了x,而不是新生成一个变量。这样并没有通过一行代码合并两个字典,而且还修改了变量x的值。

当然,我们可以做一些改变,例如,先定义一个空的字典z,然后分别将x和y与z合并,代码如下:

这段代码完美地将x和y合并,而且并未改变x和y的值,不过代码量比较多,仍然未使用一行代码合并两个字典。

下面就看看那些用一行代码解决合并字典的方法们:

1.  Python 3.9的解决方案

如果读者使用Python 3.9,那简直太幸运了,因为Python 3.9可以直接通过“|”运算符合并两个字典,简直干净利索,代码如下:

不过遗憾的是,“|”运算符只能合并字典,不能合并列表。

2. Python 3.5及以上版本的解决方案

如果读者使用的不是Python 3.9,但却是Python3.5或以上版本,如Python3.7、Python3.8等,可以采用双星(**)运算符合并两个字典,代码如下:

这里的“**”表示将字典拆成key-value对形式传入,那么{**x, **y}就表示先将x和y拆成独立的key-value对,然后再将这些key-value对覆盖新字典。

除了“**”外,还有可以处理列表的“*”,例如,下面的代码可以合并两个列表。合并原理与“**”类似。

3. Python 3.4或一下版本的解决方案

如果读者使用的是Python3.4或更低的Python版本,如Python2.7,那么如果想用一行代码解决问题,就要自己编写函数了。基本的解决思路是先将x整个复制一份,变成z,然后再使用update函数合并z与y。实现代码如下:

现在就可以使用下面的一行代码合并x和y了,而且x和y都没有改变。

print(merge_two_dicts(x,y))

如果还想合并不定数量的字典,如3个字典、5个字典,可以使用下面的函数:

4. 深度合并

前面给出的案例只能浅层合并,如果想深度合并,可以使用递归的方式。例如,要合并下面两个字典:

这两个字典的每一个key,也是一个字典,现在需要合并每一个key表示的字典,合并的结果希望是如下形式:

{'b': {2: {}, 10: {}}, 'a': {1: {}}, 'c': {11: {}}}

要完成这个功能,需要使用deepcopy函数,代码如下:

现在可以使用下面的代码合并xx和yy:

如果要合并的两个字典的key对应的value,有一个不是字典,那么无法合并,在这种情况下,value就为None,例如,要合并下面两个字典:

由于yy的b是20,而xx的b是一个字典,所以b无法合并,因此执行这段代码,会输出如下结果:

{'b': None, 'a': {1: {}}, 'c': {11: {}}}

5. 其他合并字典的方式

除了前面介绍的几种合并字典的方式,还可以用下面的2种合并方式:

(1)for in 表达式

  在Python中有一种语法,可以利用for in表达式生成列表或字典,因此,可以利用这个功能,将要合并的两个字典中的key和value单独提取出来,然后逐个写入新的字典,实现代码如下:

要理解for in表达式是如何工作的,可以先提取下面的代码:

这段代码其实是将x和y作为元组的元素,输出的结果如下:

然后for k, v in d.items()就是对这个元组进行迭代,而k和v就是提取元组中每一个元素的key和value,然后再将k和v作为新字典的key和value插入。

(2)使用chain对象

通过chain对象,可以将多个字典转换为像链表一样的结果(这个链表是可迭代的),然后再使用dict对象将其转换为字典,实现代码如下:

6. 性能大比拼

到现在为止,已经讲了很多种合并字典的方式,那么这些方式哪些效率高,哪些效率低呢?下面就来做一个实验。

其中repeat函数可以用来方便地测试一小段代码的执行时间,在默认情况下,repeat函数会将由lambda参数指定的表达式执行时间放大100万倍,也就是执行100万次这个表达式,然后统计时间总和,并且这一过程进行5遍,也就是说,repeat函数会执行lambda参数指定的表达式500万次,最后得到5组时间值(单位是秒),然后用min函数挑出最小的值。

执行这段代码,会输出如图1所示的结果:

很明显,x | y的效率最高,两个字典合并100万次,只需要不到0.5秒,而最后一种方式最慢,需要2秒,所以最快的合并字典的方式比最慢的方式整整快了4倍。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK