一、模块详细介绍
collections 包含了一些特殊的容器,针对Python内置的容器,例如:list、dict、set和tuple,提供了另外一种选择
namedtuple:可以创建包含名称的tuple;
deque:类似于list的容器,可以快速的在队列头部和尾部添加、删除元素;
Counter,dict的子类,计算可hash的对象;
OrderedDict,dict的子类,可以记住元素的添加顺序;
defaultdict,dict的子类,可以调用提供默认值的函数;
二、模块使用
Counter
counter可以支持方便,快速的计数。例如
1
2
3
4
5
6
7from collections import *
cnt = Counter()
wordList = ["a","b","c","c","a","a"]
for word in wordList:
cnt[word] += 1
print cnt
控制台输出
1 | Counter({'a': 3, 'c': 2, 'b': 1}) |
对可迭代的对象进行计数或者从另一个映射进行初始化
1 | #一个新的,空的counter c = Counter() |
Counter 对象类似于字典,如果某个项缺失,会返回0,而不是报出KeyError
1 | 'eggs','ham']) c = Counter([ |
将一个元素的数目设置为0,并不能把它从counter中删除,使用del可以将这个元素删除;
1 | 'eggs','ham']) c = Counter([ |
Counter对象支持以下三个字典不支持的方法,elements(), most_common(), subtract();
elements()返回一个迭代器,每个元素重复的次数为它的数目,顺序是任意的顺序,如果一个元素的数目少于1,那么elements()就会忽略它;
1 | 2,b=4,c=0,d=-2,e = 1) c = Counter(a= |
most_common 返回一个列表,包含counter中n个最大数目的元素,如果忽略n或者为None,most_common()将会返回counter中的所有元素,元素有着相同数目的将会以任意顺序排列;
1 | 'abracadabra').most_common(3) Counter( |
subtract(), 从一个可迭代对象中或者另一个映射(或counter)中,元素相减,类似于dict.update(),但是subtracts 数目而不是替换它们,输入和输出都有可能为0或者为负;
1 | >> c = Counter(a=4,b=2,c=0,d=-2) |
update, 从一个可迭代对象中或者另一个映射(或counter)中所有元素相加,类似于dict.upodate,是数目相加而非替换它们,另外,可迭代对象是一个元素序列,而非(key,value)对构成的序列;
1 | c |
Counter对象常见的操作,
1 | c |
在Counter对象进行数学操作,得多集合(counter中元素数目大于0)加法和减法操作,是相加或者相减对应元素的数目;交集和并集返回对应数目的最小值和最大值;每个操作均接受暑促是有符号的数目,但是输出并不包含数目为0或者为负的元素;
1 | 3,b=1,c=-2) c = Counter(a= |
deque
deque是栈和队列的一种广义实现,deque是”double-end queue”的简称;deque支持线程安全、有效内存地以近似O(1)的性能在deque的两端插入和删除元素,尽管list也支持相似的操作,但是它主要在固定长度操作上的优化,从而在pop(0)和insert(0,v)(会改变数据的位置和大小)上有O(n)的时间复杂度。
deque支持如下方法,
append(x), 将x添加到deque的右侧;
appendleft(x), 将x添加到deque的左侧;
clear(), 将deque中的元素全部删除,最后长度为0;
count(x), 返回deque中元素等于x的个数;
extend(iterable), 将可迭代变量iterable中的元素添加至deque的右侧;
extendleft(iterable), 将变量iterable中的元素添加至deque的左侧,往左侧添加序列的顺序与可迭代变量iterable中的元素相反;
pop(), 移除和返回deque中最右侧的元素,如果没有元素,将会报出IndexError;
popleft(), 移除和返回deque中最左侧的元素,如果没有元素,将会报出IndexError;
remove(value), 移除第一次出现的value,如果没有找到,报出ValueError;
reverse(), 反转deque中的元素,并返回None;
rotate(n), 从右侧反转n步,如果n为负数,则从左侧反转,d.rotate(1)等于d.appendleft(d.pop());
maxlen, 只读的属性,deque的最大长度,如果无解,就返回None;
除了以上的方法之外,deque还支持迭代、序列化、len(d)、reversed(d)、copy.copy(d)、copy.deepcopy(d),通过in操作符进行成员测试和下标索引,索引的时间复杂度是在两端是O(1),在中间是O(n),为了快速获取,可以使用list代替
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46from collections import deque
'ghi')# 新建一个deque,有三个元素 d = deque(
for ele in d:# 遍历deque
print ele.upper()
G
H
I
'j')# deque右侧添加一个元素 d.append(
'f')# deque左侧添加一个元素 d.appendleft(
# 打印deque d
deque(['f', 'g', 'h', 'i', 'j'])
# 返回和移除最右侧元素 d.pop()
'j'
# 返回和移除最左侧元素 d.popleft()
'f'
# 以列表形式展示出deque的内容 list(d)
['g', 'h', 'i']
0]# 获取最左侧的元素 d[
'g'
-1]# 获取最右侧的元素 d[
'i'
# 以列表形式展示出倒序的deque的内容 list(reversed(d))
['i', 'h', 'g']
'h' in d# 在deque中搜索
True
'jkl')# 一次添加多个元素 d.extend(
d
deque(['g', 'h', 'i', 'j', 'k', 'l'])
1)# 往右侧翻转 d.rotate(
d
deque(['l', 'g', 'h', 'i', 'j', 'k'])
-1)# 往左侧翻转 d.rotate(
d
deque(['g', 'h', 'i', 'j', 'k', 'l'])
# 以逆序新建一个deque deque(reversed(d))
deque(['l', 'k', 'j', 'i', 'h', 'g'])
# 清空deque d.clear()
# 不能在空的deque上pop d.pop()
Traceback (most recent call last):
File "<input>", line 1, in <module>
IndexError: pop from an empty deque
'abc')# 以输入的逆序向左扩展 d.extendleft(
d
deque(['c', 'b', 'a'])其他的应用
限定长度的deque提供了Unix中tail命令相似的功能
1
2
3
4
5
6
7from collections import deque
def tail(filename,n = 10):
"Return the last n lines of a file"
return deque(open(filename),n)
print tail("temp.txt",10)使用deque维护一个序列(右侧添加元素,左侧删除元素)中窗口的平均值;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19from collections import deque
import itertools
def moving_average(iterable,n = 3):
it = iter(iterable)
d = deque(itertools.islice(it,n-1))
# 第一次只有两个元素,再右移的过程中,需要先删除最左端的元素,因此现在最左端加入0
d.appendleft(0)
s = sum(d)
for ele in it:
# 删除最左端的元素,再加上新元素
s += ele - d.popleft()
# 右端添加新元素
d.append(ele)
yield s / float(n)
array = [40,30,50,46,39,44]
for ele in moving_average(array,n=3):
print elerotate()方法提供了一种实现deque切片和删除的方式,例如,del d[n]依赖于rotate方法的纯Python实现,如下,
1
2
3
4
5
6
7
8
9
10
11
12
13from collections import deque
def delete_nth(d,n):
# 将前n个元素翻转到右侧
d.rotate(-n)
# 删除第n个元素
d.popleft()
# 再将后n个元素翻转到左侧
d.rotate(n)
d = deque("abcdefg")
delete_nth(d,n = 3)
print dslice依赖于rotate方法的纯Python实现,如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20from collections import deque
def slice(d,m,n):
# 先将前面m个元素翻转到右侧
d.rotate(-m)
i = m
sliceList = []
# 依次将[m,n]区间内的元素出栈
while i < n:
item = d.popleft()
sliceList.append(item)
i+=1
# 再将出栈的元素扩展到deque右侧
d.extend(sliceList)
# 再将后面n个元素翻转到左侧
d.rotate(n)
return sliceList
d = deque("abcdefg")
print slice(d,1,5)