前言
本文主要是记录学习python的collections的笔记。collections中包含了一些常用的数据结构,在学习和使用python中,可以提高对特定场景下的实现效率。
官网链接是:https://docs.python.org/3/library/collections.html
整体来说,我认为这个库可以分为三类:
第一类,比较独立的,满足特定场景的功能。
类名 | 功能 |
---|---|
namedtuple | 命名元组,是一个工厂函数,可以创建带有参数名称的元组 |
deque | 双向队列,是一个类似于list的数据结构,但是两端都可快速的添加和删除元素 |
ChainMap | 链式映射表,是管理多个映射表的数据结构 |
Counter | 计数器,主要是统计计数的功能 |
第二类,特定功能的字典。
类名 | 功能 |
---|---|
OrderedDict | 有序字典,故名思义,就是方便记录元素的添加顺序 |
defaultdict | 带有默认值的字典 |
第三类,方便用户使用的dict/list/string结构。
类名 | 功能 |
---|---|
UserDict | 对于字典的装饰类 |
UserList | 对列表的装饰类 |
UserString | 对字符串的装饰类 |
一、相互比较独立的,满足特定场景的功能
1.1 collections.ChainMap(*maps)
概念:链式映射表的作用是把多个映射表连接成一个整体的单元;说白了,就是用一个列表list,该列表中的每个元素都是一个字典或者可映射的表;
理解这个ChainMap,需要记住以下几个注意点:
1 本质是一个列表list,列表中的元素都是字典,且列表永不为空。
2 对于查询操作,会沿着列表顺序,从头查到尾,直到第一个找到或者找不到;但是,对于写操作(添加、更改、删除)时,只会作用在第一个映射表中,即作用在list[0]。
3 ChainMap对各个字典,都是以引用计数跟踪的,也就是说,对各个字典的单独操作,都能实时反应到ChainMap中。
4 ChainMap对于字典的常规操作方法都是支持的。
5 有额外支持的一些属性和方法。
名称 | 类型 | 功能 |
---|---|---|
maps | 属性 | 保存映射表的列表对象 |
parents | 属性 | 返回一个ChainMap对象,该对象包含原对象的除第一个映射表的其它所有映射表 |
new_child(m=None) | 方法 | 返回一个ChainMap对象,该对象包含原对象的所有映射表;若m不为空,则m为第一个映射表;若m为空,则第一个映射表为空映射表 |
1.2 collections.Counter([iterable-or-mapping])
概念:计数器,是字典dict的子类,用来计数统计每个key出现的次数。
注意点:
1 key出现的次数,可正,可负,可为零。
2 查询不存在的key的次数时,返回零,而不是KeyError。
3 有额外支持的属性和方法。
名称 | 类型 | 功能 |
---|---|---|
elements() | 方法 | 返回一个迭代器,每个key重复出现的次数为其value值 |
most_common([n]) | 方法 | 返回一个列表,表示前n个最高次数的元素,列表的元素为元组,形如(key, 次数) |
subtract([iterable-or-mapping]) | 方法 | 减法操作,每个key的次数值都减去参数中对应key值的次数值 |
fromkeys(iterable) | 方法 | 没有支持实现 |
update([iterable-or-mapping]) | 方法 | 加法操作,每个key的次数值都加入参数中对应key值的次数值 |
加法操作 + | 运算符 | 效果等同于update([iterable-or-mapping]) |
减法操作 - | 运算符 | 效果等同于subtract([iterable-or-mapping]) |
最小操作 & | 运算符 | 取值为双方共有的key值,且较小值 |
最小操作 | | 运算符 | 取值为双方共有的key值,且较大值 |
取正操作 + | 运算符 | 取值为key的次数值为正的元素 |
取反操作 - | 运算符 | 取值为key的次数值为负的元素,且最终结果为正值 |
1.3 collections.deque([iterable[, maxlen]])
概念:deque是一个方便双向快速访问的队列,也可以当成stack使用;
若没有指定maxlen值,长度可无限增长;否则限定为maxlen长度;
当达到最大长度后,再添加元素时,则新元素被添加,其反方向的一个元素被挤出,即从右边添加时,左侧第一个元素被挤出;从左侧添加元素时,右侧最后一个元素被挤出。
成员属性或函数:
名称 | 类型 | 功能 |
---|---|---|
append(x) | 方法 | 从右侧添加元素X |
appendleft(x) | 方法 | 从左侧添加元素X |
clear() | 方法 | 清空内部所有元素 |
copy() | 方法 | 浅拷贝一份自身 |
count(x) | 方法 | 统计X在deque中出现的次数 |
extend(iterable) | 方法 | 从右侧方向,依次添加可迭代对象内的元素 |
extendleft(iterable) | 方法 | 从左侧方向,依次添加可迭代对象内的元素 |
index(x[, start[, stop]]) | 方法 | 返回X在deque中索引位置,可指定索引范围,若未找到,抛ValueError |
insert(i, x) | 方法 | 在i索引位置处插入元素X |
pop() | 方法 | 移除最右侧的元素,并返回该元素 |
popleft() | 方法 | 移除最左侧的元素,并返回该元素 |
remove(value) | 方法 | 删除deque中第一个出现的value值 |
reverse() | 方法 | 使deque内的元素反序排列 |
rotate(n=1) | 方法 | 滚动deque内的元素n次,n为正表示向右滚动,n为负表示向左滚动 |
maxlen | 属性 | 最大限定长度值 |
除上述方法外,deque还支持iteration, pickling, len(d), reversed(d), copy.copy(d), copy.deepcopy(d)等操作,及in操作;也支持下标索引访问,d[x],但是要注意的是下标索引时,只有最左和最右的元素是O(1)开销,其它元素是O(n)开销。
1.4 collections.namedtuple(typename, field_names, *, rename=False, defaults=None, module=None)
概念:命名元组,是指对每个位置的成员,添加一个更可读的成员变量名的元组;本质还是元组,只是可以通过成员变量名来访问,而不仅仅通过位置索引。
成员属性或函数:
名称 | 类型 | 功能 |
---|---|---|
_make(iterable) | 类方法 | 从iterable参数初始化,创建一个namedtuple对象 |
_asdict() | 方法 | 返回一个字典,key为变量名,value为对应的成员值 |
_replace(**kwargs) | 方法 | 返回一个新的namedtuple对象,并更新所指定的成员变量的值 |
_fields | 属性 | 返回一个元组,值为成员变量名 |
_field_defaults | 属性 | 返回有默认值的成员变量的字典 |
二、特定功能的字典
2.1 collections.defaultdict(default_factory=None, /[, …])
默认字典,是指在获取特定key的value值时,若不存在,则可依据default_factory来创建对应的默认值。
成员属性或函数:
名称 | 类型 | 功能 |
---|---|---|
missing(key) | 方法 | 当__getitem__()找不到对应的key值时,调用__missing__方法;依据default_factory创建默认值 |
default_factory | 属性 | 保存初始化的参数值 |
s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
d = defaultdict(list)
for k, v in s:
d[k].append(v)
sorted(d.items()) # [('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]
2.2 collections.OrderedDict([items])
概念:有序字典,故名思义,就是字典在添加元素时,是能记录其添加顺序的。但是目前从python3.7开始后,已默认支持这种功能。
成员属性或函数:
名称 | 类型 | 功能 |
---|---|---|
popitem(last=True) | 方法 | 移除并返回一个(key, value)的值,参数可以决定是从左侧还是右侧操作 |
move_to_end(key, last=True) | 方法 | 移动key值所对应的值,到最左侧或者最右侧 |
三、方便用户使用的dict/list/string结构
概念:collections.UserDict([initialdata])、collections.UserList([list])和collections.UserString(seq),实际上是对对应的字典dict、列表list和字符串str的装饰;所谓装饰是指其支持原来操作,只是多了一个data属性,用来真正的保存对应的数据。
以collections.UserDict([initialdata])为例:
import collections
ud = collections.UserDict()
ud["a"] = 1
ud["b"] = 2
print(ud) # 输出{'a': 1, 'b': 2}
for k,v in ud.data.items():
print(k, v) # 依次输出a 1,b 2
如官网中所说,其实若需要对应的功能,直接继承相应的数据类型也是可以的。