Python collections模块用法解读

440 阅读5分钟

这是我参与8月更文挑战的第20天,活动详情查看:8月更文挑战

我们都知道,Python提供了一些好用的数据类型,比如int,string, list, dict, tuple, set等,虽然这些数据结构能够很好的满足开发者的需求,但是Python还为我们提供了一个非常好用的库collections,这个库提供了很多更高级的数据结构,接下来就来介绍一下。

collections库函数一览表

函数说明
nametuple创建具有命名字段的元组子类的工厂函数
deque类似列表(list)的容器,两端都具有快速追加和弹出的功能
ChainMap类似字典(dict)的类,用于创建多个映射的单个视图
Counter字典的子类,提供了可哈希对象的计数功能
OrderedDict字典的子类,保存了他们被添加的顺序
defaultdict字典的子类,调用工厂函数来提供缺失值
UserDict封装了字典对象以便于字典子类化
UserList封装了列表对象以便于列表子类化
UserString封装了字符串对象以便于字符串子类化

namedtuple

namedtuple是用于命名元组子类的工厂函数,主要用来创建可以使用名称来访问元素的数据对象。顾名思义,nametuple就是一个命名元组,可以使用名称访问元素数据。

from collections import namedtuple

User = namedtuple('User', ['name', 'sex', 'level'])
# User = namedtuple('User', 'name sex level')  写成这种形式也可以
me = User('tigeriaf', 'male', 2)
print(me.name, me.sex, me.level)
# tigeriaf male 2

deque

deque是一种由队列结构扩展而来的双端队列(double-ended queue),普通队列只允许在队尾插入元素,在队首弹出元素;而deque能够在队列首尾两端都支持插入和弹出两种操作,所以更加灵活;而且deque由于受到GIL锁的限制,是线程安全的;在队列两端的插入和弹出操作都能够达到近乎于O(1)的时间复杂度。

deque除了实现了list常用的append、pop、extend、copy等,还实现了appendleft、popleft、extendleft,功能和append、pop、extend一致,只是在队列左侧,也就是头部进行操作。

因此,如果你遇到经常操作列表头的场景,使用deque最好。deque类的所有方法,自行操作一遍就知道了。

from collections import deque


deque1 = deque()
print(deque1)
deque1.append(1)
print(deque1)
deque1.extend([2, 3, 4])
print(deque1)
deque1.appendleft("a")
print(deque1)
deque1.extendleft(["b", "c", "d"])
print(deque1)
deque1.pop()
print(deque1)
deque1.popleft()
print(deque1)

执行结果为:
image.png
deque比普通的列表多了一些特殊方法,
如rotate(n=1)方法:向右移动n步,如果n为负,则向左移动,当双端队列不为空时,向右移动一步相当于d.appendleft(d.pop()),向左移动一步相当于d.append(d.popleft())。

deque1 = deque([1, 2, 3, 4, 5])
deque1.rotate(2)
print(deque1)
# deque([4, 5, 1, 2, 3])
deque1.rotate(-1)
print(deque1)
# deque([5, 1, 2, 3, 4])

ChainMap

ChainMap是一种类似字典(dict)的容器类,将多个映射集合到一个视图里面。当我们有多个字典或者映射,想把它们合并成为一个单独的映射时,使用ChainMap通常比创建新字典和多次调用update()快得多。

dict1 = {"a": 1, "b": 2}
dict2 = {"c": 4, "d": 5, "e": 6}
combined = ChainMap(dict2, dict1)
print(combined)
print(combined.maps)
for k, v in combined.items():
    print(k, v)

执行结果为:

image.png
其中的maps属性是一个列表,存储的是需要合并的各个映射。

Counter

Counter是字典的子类,提供了可哈希对象的计数功能。如果想要统计一个元素在给定的序列中一共出现了多少次,诸如此类的操作就可以用Counter来实现,它不仅支持字符串、列表、字典等的计数统计,而且还是对计数进行叠加,非常强大。 例如:

words = ['hello', 'world', 'tigeriaf', 'hello', 'Python', 'tigeriaf']

counter = Counter(words)
print(counter)
# Counter({'hello': 2, 'tigeriaf': 2, 'world': 1, 'Python': 1})
print(counter["hello"])
# 2

我们将一个list传入Counter中,它会自动统计list当中的每个元素的次数。 Counter还提供了most_common(n)方法,可以输出出现次数最多的前n个元素:

print(counter.most_common(2))

# [('hello', 2), ('tigeriaf', 2)]

另外,它还可以接收dict类型,我们可以直接通过一个值是int类型的dict来初始化一个Counter,比如:

counter = Counter({'hello': 3, 'tigeriaf': 2, "python": 2, "world": 1})
print(counter)
# Counter({'hello': 3, 'tigeriaf': 2, 'python': 2, 'world': 1})

OrderedDict

普通的dict不记录插入的顺序,遍历的时候也是随机的,而OrderedDict记录插入的顺序,遍历的时候也是按顺序进行。

order_dict = OrderedDict({"a": 1, "b": 2, "c": 3, "d": 4})
for k, v in order_dict.items():
    print(k, v)

defaultdict

当在字典中查找一个不存在的键时,会导致系统抛出异常,所以我们需要在查找之前做判断,判断键key是否在字典内,但是这样就很麻烦。而defaultdict可以解决这种字典key为空的情况,如果key不存在,容器会自动返回我们预先设置的默认值。需要注意的是defaultdict传入的默认值可以是一个类型,也可以是一个方法

# 使用str作为default_factory
dict1 = defaultdict(str)
print(dict1)
print(dict1["x"])
# 使用int作为default_factory
dict2 = defaultdict(int)
print(dict1)
print(dict2["x"])
# 使用list作为default_factory
dict3 = defaultdict(list)
print(dict3)
print(dict3["x"])

执行结果如下:
image.png

UserDict、UserList、UserString

这三个类是分别对字典dict、列表list和字符串str三种数据类型的封装,主要功能是便于子类化,也就是方便用户继承这些类实现自己的数据类型。

总结

更多关于collections模块的使用细节,移步官方文档 collections

最后,感谢女朋友在工作和生活中的包容、理解与支持 !