文章目录
Collections 模快
一、 简介
collections模块实现了特定目标的容器,以提供Python标准内建容器dict ,list , set , 和tuple的替代选择
通俗来说,Python内置的数据类型和方法,collections模块在这些内置类型的基础提供了额外的高性能数据类型,比如基础的字典是不支持顺序的,collections模块的OrderedDict类构建的字典可以支持顺序,collections模块的这些扩展的类用处非常大,熟练掌握该模块,可以大大简化Python代码
官方文档:【https://docs.python.org/zh-cn/3/library/collections.html】
所有子类
名称 | 功能 |
---|---|
namedtuple() | 创建命名元组子类的工厂函数 |
deque | 类似列表(list)的容器,实现了在两端快速添加(append)和弹出(pop) |
ChainMap | 类似字典(dict)的容器类,将多个映射集合到一个视图里面 |
Counter | 字典的子类,提供了可哈希对象的计数功能 |
OrderedDict | 字典的子类,保存了他们被添加的顺序 |
defaultdict | 字典的子类,提供了一个工厂函数,为字典查询提供一个默认值 |
UserDict | 封装了字典对象,简化了字典子类化 |
UserList | 封装了列表对象,简化了列表子类化 |
UserString | 封装了字符串对象,简化了字符串子类化 |
二、 Counter
1、 基本用法
一个计数器工具提供快速和方便的计数,Counter是一个dict的子类,用于计数可哈希对象。它是一个集合,元素像字典键(key)一样存储,它们的计数存储为值。计数可以是任何整数值,包括0和负数,Counter类有点像其他语言中的bags或multisets。简单说,就是对可迭代对象的里面每个元素的计数
lis = ["blue", "blue", "blue", "red", "red", "green", "green", "blue", "red", "red"]
# 传统方法计数
count_lis = {}
for i in lis:
if count_lis.get(i, -1) == -1:
# 说明获取值失败,没有存入值
count_lis[i] = 1
continue
count_lis[i] += 1
print(count_lis)
# 使用Counter计数
from collections import Counter
count = Counter(lis) # 参数是可迭代对象
print(dict(count))
# 也可以是
coun = Counter(a=4, c=5) # 表示有4个a,5个c
print(coun)
2、 常用函数
函数 | 作用 |
---|---|
del count[key] | 删除指定键key |
count.elements() | 返回一个迭代器 |
most_common(n) | 返回一个列表,其中包含 n 个最常见的元素及出现次数 |
subtract(iterable or mapping) | 从迭代对象或映射对象减去元素。但是是减去,而不是替换 |
update(iterable or mapping) | 从迭代对象或映射对象添加元素 |
clean() | 清空里面的内容 |
get(key) | 得到对应键的值 |
items() | 得到对象内所有的键值对 |
from collections import Counter
lis = ["blue", "blue", "blue", "red", "red", "green", "green", "blue", "red", "red"]
count = Counter(lis) # 参数是可迭代对象
count.update(["r", "s", "r"]) # 向里面添加元素
del(count["r"]) # 删除键"r"
print(count.elements()) # 返回可迭代对象
print(count.most_common(3)) # 只输出前三个数量最多的元素
count.subtract(["z", "r", "r"]) # 减去里面的元素,注意,不是删除
print(count.items()) # 得到键值对
count.clear() # 清空内容
3、 数学运算
加和减,结合计数器,通过加上或者减去元素的相应计数。交集和并集返回相应计数的最小或最大值。每种操作都可以接受带符号的计数,但是输出会忽略掉结果为零或者小于零的计数
from collections import Counter
count = Counter(a=3, b=-4) # 参数是可迭代对象
c_div = Counter(a=1, b=2, c=3) # 创建一个新的对象
print(count)
# 进行数学操作,如果c_div有count里面的键,则进行相应的数学运算
print(count - c_div)
print(count + c_div)
# 单目数学运算
print(+count) # 只取值为正数的键
print(-count) # 对负数取反,并且正数忽略
# 进行逻辑运算
print(count & c_div) # 交集运算
print(count | c_div) # 并集运算
# 比较运算
print(count == c_div) # 其为判断每一个键值对是否相同
三、 deque
双端队列,可以快速的从另外一侧追加和推出对象,deque是一个双向链表,针对list连续的数据结构插入和删除进行优化。它提供了两端都可以操作的序列,这表示在序列的前后你都可以执行添加或删除操作。双向队列(deque)对象支持以下方法:
方法 | 作用 |
---|---|
append(x) | 添加元素到右端 |
appendleft(x) | 添加元素到左端 |
clear() | 清空所有的元素 |
copy() | 浅拷贝 |
count(x) | 计算值为x出现的次数 |
extend(iterable) | 拓展队列的右侧 |
extendleft(iterable) | 拓展队列的左侧,反顺序添加 |
index(x[, start[, end]]) | 返回元素 x 的索引 |
insert(i, x) | 在 x 位置插入元素 i |
pop() | 删除最右边的元素并返回该元素 |
popleft() | 删除最左边的元素并返回该元素 |
remove(val) | 移除队列中的第一个 val 元素 |
reverse() | 逆序排列 |
rotate(n) | 向右循环移动 n 步。 如果 n 是负数,就向左循环 |
maxlen | 返回队列的最大长度 |
四、 OrderedDict
有序词典就像常规词典一样,但有一些与排序操作相关的额外功能,popitem()
方法有不同的签名。它接受一个可选参数来指定弹出哪个元素。move_to_end()
方法,可以有效地将元素移动到任一端
与dict字典的不同之处:
- 常规的
dict
被设计为非常擅长映射操作,跟踪插入顺序是次要的 OrderedDict
旨在擅长重新排序操作。空间效率、迭代速度和更新操作的性能是次要的- 算法上,
OrderedDict
可以比dict
更好地处理频繁的重新排序。这使其适用于跟踪最近的访问 - 对于
OrderedDict
,相等操作检查匹配顺序 OrderedDict
类的popitem()
方法有不同的签名。它接收一个可选参数来指定弹出哪个元素OrderedDict
类有一个move_to_end()
方法,可以有效地将元素移动到任意一端Python 3.8
之前,dict
缺少__reversed__()
方法
OrderedDict
特殊功能
方法 | 作用 |
---|---|
popitem(last=True) | 将对象中的元素从一侧移除,并返回移除的键值对 |
move_to_end(key, last=True) | 将现有键移动到有序字典的任一端 |
reversed(OrderedDict) | 有序字典提供了逆序迭代的支持 |
五、 nametuple
1、 简介
生成可以使用名字来访问元素内容的tuple子类,命名元组赋予每个位置一个含义,提供可读性和自文档性。它们可以用于任何普通元组,并添加了通过名字获取值的能力,通过索引值也是可以的
2、 构造函数
namedtuple(typename,field_names,*, rename=False, default=None, module=None)
3、 常用方法
为了防止字段冲突,方法和属性以下划线开始
方法 | 作用 |
---|---|
_make(iterable) | 类方法从存在的序列或迭代实例中创建一个新实例 |
_asdict() | 返回一个新的dict ,它将字段名称映射到它们对应的值 |
_replace(**kwargs) | 返回一个新的命名元组实例,并将指定域替换为新的值 |
_fields | 字符串元组列出了字段名,用于提醒和从现有元组创建一个新的命名元组类型 |
_field_defaults | 字典将字段名映射到默认值 |
getattr() | 获取对应元素的属性值 |
from collections import namedtuple
tup = namedtuple('tup', ['a', 'b', 'v'], rename=True, defaults=[8, 9, 10]) # 创建对象
print(tup._field_defaults) # 给字段名设置defaults里面的默认值
tup = tup(0, 1, 2) # 给里面的字段名赋值
print(getattr(tup, "a"), tup.a) # 获取属性值
print(tup._fields) # 获取字段名
六、 defaultdict
1、 简介
在普通的字典中,获取一个key
有两种方法,第一个使用get(key)
,第二种是通过索引来获取值
当使用索引来获取键值对时,如果应用的key
不存在,就会抛出KeyError
。如果希望key
不存在时,返回一个默认值,就可以用defaultdict
2、 构造函数
defaultdict(default_factory=None, /[, ...])
返回一个新的类似字典的对象。defaultdict
是内置dict
类的子类。它重载了一个方法并添加可写的实例变量。其余功能与dict
类相同
default_factory
:第一个参数用于为该属性提供初始值,默认为None
。所有其他参数(包括关键字参数)都相当于传递给dict
的构造函数,还支持一下方法作为扩展:__missing__(key)
-
如果
default_factory
属性为None
,则调用本方法会抛出KeyError
异常,附带参数key
-
如果
default_factory
不为None
,则它被(不带参数地)调用来为key
提供一个默认值,这个值和key
作为一对键值对被插入到字典中,并作为本方法的返回值返回
3、 default_factory
如果不存在,该对象会自动插入一个默认数据类型来代替
3.1 list
使用 list 作为 default_factory,很轻松地将(键-值对组成的)序列转换为(键-列表组成的)字典
from collections import defaultdict
s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
# 第一种创建方法
d = defaultdict(list)
for k, v in s:
d[k].append(v)
print(d)
print(d["green"]) # 如果不存在,返回空列表,并且创建该对象
print(sorted(d.items()))
# 第二种创建方法
d_ = {}
for k, v in s:
d_.setdefault(k, []).append(v)
print(d_)
3.2 int
设置 default_factory为int,使defaultdict用于计数(类似其他语言中的 bag或multiset)
from collections import defaultdict
s = "mississippi"
# 创建方法
d = defaultdict(int)
for k in s:
d[k] += 1 # 计数作用
print(d)
3.3 set
设置 default_factory 为 set 使 defaultdict 用于构建 set 集合
from collections import defaultdict
s = [('red', 1), ('blue', 2), ('red', 3), ('blue', 4), ('red', 1), ('blue', 4)]
# 创建方法
d = defaultdict(set)
for k, v in s:
d[k].add(v)
print(d)
3.4 自定义对象
from collections import defaultdict
class Test:
def printN(self):
print(self.n)
def setN(self, i):
self.n = i
name = "abcdefghij"
d = defaultdict(Test)
for i in range(10):
d[name[i]].setN(i)
d["a"].printN() # 输出数值
print(d)
七、 ChainMap
1、 简介
一个ChainMap
类是为了将多个映射快速的链接到一起,这样它们就可以作为一个单元处理。它通常比创建一个新字典和多次调用 update()
要快很多
这个类可以用于模拟嵌套作用域,并且在模版化的时候比较有用
创建对象:
cm = ChainMap(*maps) # 传入映射对象
2、 常用方法
方法 | 作用 |
---|---|
maps | 一个可以更新的映射列表 |
new_child(m=None, **kwargs) | 如果指定了m则添加映射到对象前面,返回新映射 |
parents | 返回一个新的 ChainMap 包含所有的当前实例的映射,跳过第一个映射 |
代码实例:
from collections import ChainMap
cm = ChainMap({"h": 1})
print(cm.maps) # 返回列表
print(cm.new_child({"a": 2, "b": 3})) # 添加映射
print(list(cm)) # 只返回键,不返回值
print(cm.new_child({"a": 2}).new_child({"b": 4}).parents) # 返回除了第一个以外的其他对象
对于ChainMap对象,我们可以直接使用键取值,也可以直接使用字典的其他方法,就像它是一个单一的字典
八、 UserDict
用作字典对象的外包装。对这个类的需求已部分由直接创建 dict
的子类的功能所替代;不过,这个类处理起来更容易,因为底层的字典可以作为属性来访问
dic = UserDict([initialdata])
九、 UserList
对这个类的需求已部分由直接创建list
的子类的功能所替代;不过,这个类处理起来更容易,因为底层的列表可以作为属性来访问
lis = UserList([list])
子类化的要求: UserList 的子类需要提供一个构造器,可以无参数调用,或者一个参数调用。返回一个新序列的列表操作需要创建一个实现类的实例。它假定了构造器可以以一个参数进行调用,这个参数是一个序列对象,作为数据源
如果一个分离的类不希望依照这个需求,所有的特殊方法就必须重写;请参照源代码进行修改
十、 UserString
用作字符串对象的外包装。对这个类的需求已部分由直接创建 str
的子类的功能所替代;不过,这个类处理起来更容易,因为底层的字符串可以作为属性来访问
str_ = UserString(seq)