天天看点

Python常用标准库及第三方库5-collections模块

作者:大刚测试开发实战

一、collections模块简介

官方文档:https://docs.python.org/zh-cn/3.7/library/collections.html

collections是Python标准库中自带的一个数据结构常用模块。这个模块实现了特定目标的容器,以提供Python标准内建容器 dict , list , set , 和 tuple 的替代选择。

对象 作用
namedtuple() 创建命名元组子类的工厂函数
deque 类似列表(list)的容器,实现了在两端快速添加(append)和弹出(pop)
ChainMap 类似字典(dict)的容器类,将多个映射集合到一个视图里面
Counter 字典的子类,提供了可哈希对象的计数功能
OrderedDict 字典的子类,保存了他们被添加的顺序
defaultdict 字典的子类,提供了一个工厂函数,为字典查询提供一个默认值
UserDict 封装了字典对象,简化了字典子类化
UserList 封装了列表对象,简化了列表子类化
UserString 封装了字符串对象,简化了字符串子类化

二、ChainMap对象

一个 ChainMap 将多个字典或者其他映射组合在一起,创建一个单独的可更新的视图。它通常比创建一个新字典和多次调用 update() 要快很多。 如果没有 maps 被指定,就提供一个默认的空字典,这样一个新链至少有一个映射。

底层映射被存储在一个列表中。这个列表是公开的,可以通过 maps 属性存取和更新。没有其他的状态。

搜索查询底层映射,直到一个键被找到。不同的是,写、更新和删除只操作第一个映射。

ChainMap 通过引用合并底层映射。所以,如果一个底层映射更新了,这些更改会反映到 ChainMap 。

支持所有常用字典方法。另外还有一个 maps 属性(attribute),一个创建子上下文的方法(method), 一个存取它们首个映射的属性(property)。

from collections import *

"""ChainMap对象"""
base_dic = {"name": "Python", "age": 28, "city": "Nanjing"}
new_dic = {"city": "Shanghai", "job": "tester", "sex": "man"}
last = {"money": 999}
# 获取ChainMap对象的key列表,自动去重
print(list(ChainMap(base_dic, new_dic, last)))
# 获取ChainMap对象的maps列表
print(ChainMap(base_dic, new_dic, last).maps)
'''
ChainMap({'name': 'Python', 'age': 28, 'city': 'Nanjing'}, {'city': 'Shanghai', 'job': 'tester', 'sex': 'man'}, {'money': 999})
['money', 'city', 'job', 'sex', 'name', 'age']
[{'name': 'Python', 'age': 28, 'city': 'Nanjing'}, {'city': 'Shanghai', 'job': 'tester', 'sex': 'man'}, {'money': 999}]
'''           

三、Counter对象

一个 Counter 是一个 dict 的子类,用于计数可哈希对象。它是一个集合,元素像字典键(key)一样存储,它们的计数存储为值。计数可以是任何整数值,包括0和负数。 Counter 类有点像其他语言中的 bags或multisets。

1.Counter计数功能

Counter对象类似于字典,形式为Counter({key1: value1, key2: value2}),其中value为对应key出现的次数;如果某个项缺失,会返回0,而不是报出KeyError。

# Counter计数功能
w_list = ["php", "python", "go", "ruby", "python", "java", "go", "python", "c++"]
count = Counter(w_list)
# Counter对象类似于字典,value为对应key出现的数量
print(count)  # Counter({'python': 3, 'go': 2, 'php': 1, 'ruby': 1, 'java': 1, 'c++': 1})
print(count.items())  # dict_items([('php', 1), ('python', 3), ('go', 2), ('ruby', 1), ('java', 1), ('c++', 1)])
print(count.keys())  # dict_keys(['php', 'python', 'go', 'ruby', 'java', 'c++'])
print(count.values())  # dict_values([1, 3, 2, 1, 1, 1])
# 如果某个项缺失,会返回0,而不是报出KeyError
print(count["python"])  # 3 返回该元素的数量
print(count["kotlin"])  # 0           

2. most_common 列表排列顺序

返回一个列表,提供 n 个频率最高的元素和计数。 如果没提供 n ,或者是 None , most_common() 返回计数器中的所有元素。相等个数的元素顺序随机。

列表中的元素形式为二元组,按照key数量从大到小排列,n表示列表截取的二元组个数

w_list = ["php", "python", "go", "ruby", "python", "java", "go", "python", "c++"]
count = Counter(w_list)
# most_common
# 返回一个列表,列表中的元素形式为二元组,按照key数量从大到小排列,n表示列表截取的二元组个数
print(count.most_common())  # [('python', 3), ('go', 2), ('php', 1), ('ruby', 1), ('java', 1), ('c++', 1)]
print(count.most_common(n=3))  # [('python', 3), ('go', 2), ('php', 1)]
print(count.most_common(n=2))  # [('python', 3), ('go', 2)]           

3.update 更新可迭代对象列表

从 迭代对象 计数元素或者 从另一个 映射对象 (或计数器) 添加。 像 dict.update() 但是是加上,而不是替换。另外,迭代对象 应该是序列元素,而不是一个 (key, value) 对。

# update 更新可迭代对象列表
# 将一个可迭代对象列表的元素添加到另一个可迭代对象中
list_a = ["php", "python", "go", "python", "java", "go", "python"]
list_b = [1, "php", 3, 3, 88, 77, "python", 99]
c1 = Counter(list_a)
c2 = Counter(list_b)
print(c1)  # Counter({'python': 3, 'go': 2, 'php': 1, 'java': 1})
print(c2)  # Counter({3: 2, 1: 1, 'php': 1, 88: 1, 77: 1, 'python': 1, 99: 1})
# 将Counter对象c2中的元素添加到Counter对象c1中,存在重复元素、累加计算
c1.update(c2)
print(c1)  # Counter({'python': 4, 'php': 2, 'go': 2, 3: 2, 'java': 1, 1: 1, 88: 1, 77: 1, 99: 1})           

四、OrderedDict对象

有序词典就像常规词典一样,但有一些与排序操作相关的额外功能。

'''OrderedDict对象'''
# OrderedDict有序字典
# 按照插入的顺序来排列,字典不会因为key或value的值,再自动排序
od = OrderedDict()
od["k1"] = "tom"
od["k2"] = "lucy"
od["k3"] = "jerry"
print(od)  # OrderedDict([('k1', 'tom'), ('k2', 'lucy'), ('k3', 'jerry')])
# 指定一个列表,把列表中的值,作为字典的key,生成一个字典
info = ["name", "age", "height", "weight"]
print(od.fromkeys(info))  # OrderedDict([('name', None), ('age', None), ('height', None), ('weight', None)])
print(od.fromkeys(info, 20))  # OrderedDict([('name', 20), ('age', 20), ('height', 20), ('weight', 20)])           

1.popitem(last=True)

有序字典的 popitem() 方法移除并返回一个 (key, value) 键值对。 如果 last 值为真,则按 LIFO 后进先出的顺序返回键值对,否则就按 FIFO 先进先出的顺序返回键值对。

od = OrderedDict()
od["k1"] = "tom"
od["k2"] = "lucy"
od["k3"] = "jerry"
# 先进先出-从开头开始删除
od.popitem(last=False)
print(od)  # OrderedDict([('k2', 'lucy'), ('k3', 'jerry')])
# 后进先出-从末尾开始删除
od.popitem(last=True)
print(od)  # OrderedDict([('k1', 'tom'), ('k2', 'lucy')])           

2.move_to_end(key, last=True)

将现有 key 移动到有序字典的任一端。 如果 last 为真值(默认)则将元素移至末尾;如果 last 为假值则将元素移至开头。如果 key 不存在则会触发 KeyError。

od = OrderedDict()
od["k1"] = "tom"
od["k2"] = "lucy"
od["k3"] = "jerry"
# 将指定key移动至末尾
od.move_to_end(last=True, key="k2")
print(od)  # OrderedDict([('k1', 'tom'), ('k3', 'jerry'), ('k2', 'lucy')])
# 将指定key移动至开头
od.move_to_end(last=False, key="k2")
print(od)  # OrderedDict([('k2', 'lucy'), ('k1', 'tom'), ('k3', 'jerry')])           

五、deque队列

Deque模块是Python标准库collections中的一项,它提供了两端都可以操作的序列,这意味着你可以在序列前后都执行添加或删除,并且可以限制队列容量。

1.deque常用方法

方法 作用
append(x) 添加x到最右端
appendleft(x) 添加x到最左端
clear() 移除所有元素,使其长度为0.
copy() 创建一份浅拷贝
count(x) 计算deque中x元素的个数
extend(iterable) 扩展deque的右侧,向deque中添加iterable中的元素
extendleft(iterable) 扩展deque的左侧,向deque中添加iterable中的元素
index(x[, start[, stop]]) 返回 x 在 deque 中的位置(在索引 start 之后,索引 stop 之前)返回第一个匹配项,如果未找到则引发 ValueError
insert(i, x) 在位置 i 插入 x
pop() 移去并且返回一个元素,deque 最右侧的那一个。 如果没有元素的话,就引发一个 IndexError。
popleft() 移去并且返回一个元素,deque 最左侧的那一个。 如果没有元素的话,就引发 IndexError。
remove(value) 移除找到的第一个 value。 如果没有的话就引发ValueError。
reverse() 将deque逆序排列。返回 None 。
rotate(n=1) 向右循环移动 n 步。 如果 n 是负数,就向左循环。如果deque不是空的,向右循环移动一步就等价于 d.appendleft(d.pop()) , 向左循环一步就等价于 d.append(d.popleft()) 。

创建队列

# 创建双向队列
cd = collections.deque()           

添加元素

# append-向右边添加元素
cd.append("python")
cd.append("java")
cd.append("c++")
print(cd)  # deque(['python', 'java', 'c++'])
# appendleft-向左边添加元素
cd.appendleft("php")
cd.appendleft("js")
print(cd)  # deque(['js', 'php', 'python', 'java', 'c++'])
# insert-在指定位置插入元素
cd.insert(0, "000")
print(cd)  # deque(['000', 'js', 'php', 'python', 'java', 'c++'])           

扩展队列

# extend-从队列右边扩展元素
cd.extend(["name", "age", "height"])
print(cd)  # deque(['js', 'php', 'python', 'java', 'c++', 'name', 'age', 'height'])
# extend-从队列左边扩展元素
cd.extendleft(("kotlin", "golang"))
print(cd)  # deque(['golang', 'kotlin', 'js', 'php', 'python', 'java', 'c++', 'name', 'age', 'height'])           

查找元素索引位置

# index-查找某个元素的索引位置
print(cd.index("java"))  # 6           

删除队列中的元素

# 删除队列中的元素
# pop-从队列右边开始删除一个元素
cd.pop()  # 'age'元素被删除
print(cd)  # deque(['golang', 'kotlin', '000', 'js', 'php', 'python', 'java', 'c++', 'name', 'age'])
# popleft-从队列左边开始删除一个元素
cd.popleft()  # '000'元素被删除
print(cd)  # deque(['kotlin', '000', 'js', 'php', 'python', 'java', 'c++', 'name', 'age'])
# remove-删除指定元素
cd.remove("c++")
print(cd)  # deque(['kotlin', '000', 'js', 'php', 'python', 'java', 'name', 'age'])           

队列反转

# 队列反转
cd.reverse()
print(cd)  # deque(['age', 'name', 'java', 'python', 'php', 'js', '000', 'kotlin'])           

清空队列

# 清空队列
cd.clear()
print(cd)  # deque([])           

2.deque常用属性

属性 作用
maxlen Deque的最大尺寸,如果没有限定的话就是 None 。

限制deque长度

# maxlen-限制deque的长度,当deque长度超过限制时,另一边的元素会自动删除
cf = collections.deque(maxlen=3)
# 从右边添加,超长时自动删除左边的元素
cf.append("python")
cf.append("java")
cf.append("c++")
cf.append("c")  # 此时会自动删除左边的元素"python"
print(cf)  # deque(['java', 'c++', 'c'], maxlen=3)
# 从左边添加,超长时自动删除右边的元素
cf.appendleft("go")  # 此时会自动删除右边的元素"c"
print(cf)  # deque(['go', 'java', 'c++'], maxlen=3)