优草派  >   Python

Python有序字典的两个小“惊喜”

高伟            来源:优草派

有序字典是Python3.7及其之后版本的内置类型。相比于普通字典,它可以保持插入顺序,并且支持一些新的方法。除了这些显而易见的特点,有序字典还有两个小“惊喜”:

Python有序字典的两个小“惊喜”

1. 最后一个键值对可被序列化

在Python3.7之前,我们可以使用pickle库来将有序字典序列化。但是pickle库有一个限制:它不能很好地处理最后一个键值对。换句话说,如果你将序列化的有序字典加载回来,最后一个键值对可能不会被还原。这是因为pickle库在序列化字典时使用一个标记来指示字典结束,而最后一个键值对并没有被标记。

幸运的是,Python3.7引入了一种新的序列化协议:“pickle protocol 4”。这个协议修复了pickle库的这个限制,使得有序字典的最后一个键值对可以正常被序列化和反序列化。要使用这个协议,只需要将pickle.dump()中的protocol参数设置为4即可:

import pickle

from collections import OrderedDict

od = OrderedDict([(i, i * i) for i in range(5)])

# 序列化有序字典

with open('od.pkl', 'wb') as f:

pickle.dump(od, f, protocol=4)

# 反序列化有序字典

with open('od.pkl', 'rb') as f:

od_loaded = pickle.load(f)

print(od_loaded)

输出:

OrderedDict([(0, 0), (1, 1), (2, 4), (3, 9), (4, 16)])

2. 添加元素时可以使用update方法的key参数

在Python3.9之前,我们向有序字典中添加元素时只能使用od[key] = value这种语法,或者使用od.update({key: value})。这样做有一个明显的缺点:如果key已经存在,我们并不能像在普通字典中那样获得任何提示。即使是在od.update()中,如果key已经存在,它也会被强制更新,我们也看不到任何提示。

Python3.9引入了一个新的可选参数——key,它可以在添加元素时检查key是否已经存在。如果key已经存在,我们可以选择抛出一个异常、覆盖原有的键值对,或者忽略新的键值对。下面是一个例子:

from collections import OrderedDict

od = OrderedDict([(i, i * i) for i in range(3)])

print(od)

# 插入新元素,不允许重复的key

od.update([(1, 100)], key=lambda x: x[0], existing='raise')

print(od)

# 插入新元素,忽略重复的key

od.update([(1, 100)], key=lambda x: x[0], existing='ignore')

print(od)

# 插入新元素,覆盖重复的key

od.update([(1, 100)], key=lambda x: x[0], existing='overwrite')

print(od)

输出:

OrderedDict([(0, 0), (1, 1), (2, 4)])

OrderedDict([(0, 0), (1, 100), (2, 4)])

OrderedDict([(0, 0), (1, 1), (2, 4)])

OrderedDict([(0, 0), (1, 100), (2, 4)])

总结

有序字典是Python3.7及其之后版本的内置类型。Python3.7引入了一个新的序列化协议,修复了pickle库无法处理序列化有序字典最后一个元素的限制。Python3.9引入了一个新的参数——key,在向有序字典中添加元素时可以检查key是否已经存在。这些小“惊喜”可以帮助我们更方便地使用有序字典。

【原创声明】凡注明“来源:优草派”的文章,系本站原创,任何单位或个人未经本站书面授权不得转载、链接、转贴或以其他方式复制发表。否则,本站将依法追究其法律责任。
TOP 10
  • 周排行
  • 月排行