- Collections 模快
- 一、 简介
- 二、 Counter
- 1、 基本用法
- 2、 常用函数
- 3、 数学运算
- 三、 deque
- 四、 OrderedDict
- 五、 nametuple
- 1、 简介
- 2、 构造函数
- 3、 常用方法
- 六、 defaultdict
- 1、 简介
- 2、 构造函数
- 3、 default_factory
- 3.1 list
- 3.2 int
- 3.3 set
- 3.4 自定义对象
- 七、 ChainMap
- 1、 简介
- 2、 常用方法
- 八、 UserDict
- 九、 UserList
- 十、 UserString
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、 基本用法import collections print(collections.__all__) # 查看对象中的所有子类
一个计数器工具提供快速和方便的计数,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、 常用函数Counter创建对象的时候,可以传入字符串,可迭代对象,Counter对象,或mapping映射等
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如果deque不是空的,向右循环移动一步就等价于
d.appendleft(d.pop())
, 向左循环一步就等价于d.append(d.popleft())
同时,列表可以使用的方法,在队列中都可以使用
有序词典就像常规词典一样,但有一些与排序操作相关的额外功能,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、 简介参数:
last
:是否从最后一个元素开始进行操作,默认为True
key
:将现有的键移动到有序字典的任意端,last=True
时,从现有的键移动到右端
生成可以使用名字来访问元素内容的tuple子类,命名元组赋予每个位置一个含义,提供可读性和自文档性。它们可以用于任何普通元组,并添加了通过名字获取值的能力,通过索引值也是可以的
2、 构造函数namedtuple(typename,field_names,*, rename=False, default=None, module=None)
3、 常用方法参数:
typename
:该参数指定所创建的tuple
子类类名,相当于用户定义了一个新类field_names
:该参数是一个字符串序列,可以是["x", "y"] 或 "x y" 或 "x, y"
等,其可以为存字符串,有空白或逗号分隔开元素名。任何有效的标识符都可以作为字段名rename
:如果rename
为真,无效字段名会自动转换成位置名,如["x", "1", "def", "abc", "x"] -> ["x", "_1", "_2", "abc", "_4"]
消除不合法的标识符和重复字段default
: 可以为None
或者是一个默认值的iterable
。如果一个默认值域必须跟其他没有默认值的域在一起出现,defaults
就应用到最右边的参数。比如如果域名['x', 'y', 'z']
和默认值(1, 2)
,那么x
就必须指定一个参数值 ,y
默认值1
,z
默认值2
module
:如果设置了该参数,那么该类位于该模快下,因此该自定义类的__module__
属性将被设为该参数值
为了防止字段冲突,方法和属性以下划线开始
_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
defaultdict(default_factory=None, /[, ...])
返回一个新的类似字典的对象。defaultdict
是内置dict
类的子类。它重载了一个方法并添加可写的实例变量。其余功能与dict
类相同
default_factory
:第一个参数用于为该属性提供初始值,默认为None
。所有其他参数(包括关键字参数)都相当于传递给dict
的构造函数,还支持一下方法作为扩展:__missing__(key)
-
如果
default_factory
属性为None
,则调用本方法会抛出KeyError
异常,附带参数key
-
如果
default_factory
不为None
,则它被(不带参数地)调用来为key
提供一个默认值,这个值和key
作为一对键值对被插入到字典中,并作为本方法的返回值返回
如果不存在,该对象会自动插入一个默认数据类型来代替
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方法,返回一个空的 list。 list.append() 操作添加值到这个新的列表里。当再次存取该键时,就正常操作,list.append() 添加另一个值到列表中。这个计数比它的等价方法dict.setdefault()要快速和简单
设置 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、 常用方法一个
ChainMap
将多个字典或者其他映射组合在一起,创建一个单独的可更新的视图。 如果没有 maps 被指定,就提供一个默认的空字典,这样一个新链至少有一个映射底层映射被存储在一个列表中。这个列表是公开的,可以通过 maps 属性存取和更新。没有其他的状态
搜索查询底层映射,直到一个键被找到。不同的是,写,更新和删除只操作第一个映射
一个
ChainMap
通过引用合并底层映射。 所以,如果一个底层映射更新了,这些更改会反映到ChainMap
支持所有常用字典方法。另外还有一个 maps 属性(attribute),一个创建子上下文的方法(method), 一个存取它们首个映射的属性(property)
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模拟字典的类。 这个实例的内容保存在一个常规字典中,它可以通过
UserDict
实例的data
属性来访问。 如果提供了 initialdata,则data
会用其内容来初始化;请注意对 initialdata 的引用将不会被保留,以允许它被用于其他目的print(type(dic), type(dic.data)) # 使用data属性返回字典数据
对这个类的需求已部分由直接创建list
的子类的功能所替代;不过,这个类处理起来更容易,因为底层的列表可以作为属性来访问
lis = UserList([list])
模拟一个列表。这个实例的内容被保存为一个正常列表,通过
UserList
的data
属性存取。实例内容被初始化为一个 list 的copy,默认为[]
空列表。 list 可以是迭代对象,比如一个Python列表,或者一个UserList
对象可以使用
data
属性访问UserList
里面的内容
子类化的要求: UserList 的子类需要提供一个构造器,可以无参数调用,或者一个参数调用。返回一个新序列的列表操作需要创建一个实现类的实例。它假定了构造器可以以一个参数进行调用,这个参数是一个序列对象,作为数据源
如果一个分离的类不希望依照这个需求,所有的特殊方法就必须重写;请参照源代码进行修改
十、 UserString用作字符串对象的外包装。对这个类的需求已部分由直接创建 str
的子类的功能所替代;不过,这个类处理起来更容易,因为底层的字符串可以作为属性来访问
str_ = UserString(seq)
模拟一个字符串对象。这个实例对象的内容保存为一个正常字符串,通过
UserString
的data
属性存取。实例内容初始化设置为 seq 的copy。seq 参数可以是任何可通过内建str()
函数转换为字符串的对象可以使用
data
属性来访问UserString
返回字符串