一、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)