collections提供了一组高效的容器数据类型,可以作为Python通用容器(tuple、list、dict)的补充。熟练掌握这些容器类型,不仅可以让我们写出的代码更加Pythonic,也可以提高我们程序的运行效率。
构造方法 | 说明 |
---|---|
namedtuple() | 创建拥有命名域的元组 |
deque | 创建双端队列 |
Counter | 创建计数器 |
OrderedDict | 创建有序字典 |
defaultdict | 创建具有默认值的字典 |
命名元组——namedtuple()
我们可以为元组中的每个位置起一个名字,名字会被作为对象的属性域,增强了代码的可读性。
此外,命名元组并不会为每个实例创建,所以命名元组是轻量级的,并不会比普通元组差。
1 | from collections import namedtuple |
1 | # 定义一个命名元组,并创建一个实例 |
Point(x=3, y=4)
1 | # 可以通过实例的属性名访问元组中不同的域,也可以像普通元祖一样使用 |
3 4
3 4
1 | # 从一个已有的序列创建 |
Point(x=3, y=4)
1 | # 转化为字典 |
OrderedDict([('x', 3), ('y', 4)])
双向列表——deque
class collections.deque([iterable[, maxlen]])
使用list存储数据时,按索引访问元素很快(O(1)),但是插入和删除元素就很慢了(O(n)),deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈:
- dequeue在两端的操作O(1),方便高效的实现各种栈和队列
- dequeue在中间的操作O(n),如需随机存取还应使用普通列表
1 | from collections import deque |
1 | # 创建双端列表 |
deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
1 | # 默认右端操作 |
deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
1 | # 支持左端操作 |
deque([-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
1 | # 数组旋转 |
deque([4, 5, 1, 2, 3])
1 | # 实现一个无尽换换的跑马灯 |
计数器——Counter
1 | from collections import Counter |
创建计数器
class collections.Counter([iterable-or-mapping])
可以由任意的可迭代对象来创建计数器,Counter会对可迭代对象中的相同对象计数统计,返回一个计数字典,以不同对象为key,以该对象出现次数为value。
1 | a = Counter() |
Counter()
1 | b = Counter(range(3)) |
Counter({0: 1, 1: 1, 2: 1})
1 | c = Counter('hello') |
Counter({'e': 1, 'h': 1, 'l': 2, 'o': 1})
1 | d = Counter(a=1,b=2.1) |
Counter({'a': 1, 'b': 2.1})
1 | x = Counter({'a':1,'b':0,'c':-2}) |
Counter({'a': 1, 'b': 0, 'c': -2})
Counter对象是字典的子类
Counter对象与内置dict的显著差异是Counter会自动为新的键值创建默认值0
1 | # 不存在的键,默认返回0,但是如果只是访问不会自动添加新的键,等价于x.get('d',0) |
0
Counter({'a': 1, 'd': 1, 'b': 0, 'c': -2})
1 | # 存在性 |
True
1 | # 返回视图 |
['a', 'c', 'b', 'd']
[1, -2, 0, 1]
[('a', 1), ('c', -2), ('b', 0), ('d', 1)]
Counter的常用方法
1 | x = Counter({'a':2,'b':0,'c':-2}) |
Counter({'a': 2, 'b': 0, 'c': -2})
elements()
elements方法用户迭代地展示Counter内的所有元素,按元素的计数重复该元素,如果该元素的计数小于1,那么Counter就会忽略该元素,不进行展示。
1 | list(x.elements()) |
['a', 'a']
most_common([k])
most_common函数返回Counter中次数最多的k个元素,如果N没有提供或者是None,那么就会返回所有元素。
1 | x.most_common() |
[('a', 2), ('b', 0), ('c', -2)]
1 | x.most_common(2) |
[('a', 2), ('b', 0)]
clear()
清除所有元素的统计次数
1 | x.clear() |
Counter()
subtract([iterable-or-mapping])
substract方法接收一个可迭代或者可映射的对象,针对每个元素减去参数中的元素对应的次数。
1 | x.subtract('abc') |
Counter({'a': 1, 'b': -1, 'c': -3})
update([iterable-or-mapping])
update方法的功能和substract方法的功能正好相反,它接收一个可迭代或者可映射的对象,针对每个元素加上参数中的元素对应的次数。
1 | x.update('bcd') |
Counter({'a': 1, 'b': 0, 'c': -2, 'd': 1})
Counter对象运算
注意:Counter对象的运算会自动忽略掉小于等于0的元素,也常常通过这种方法去除Counter对象中小于等于0的元素。
1 | x = Counter({'a':1,'b':0,'c':-2,'d':3}) |
(Counter({'a': 1, 'b': 0, 'c': -2, 'd': 3}), Counter({'a': 2, 'd': 1, 'e': 2}))
1 | x + y |
Counter({'a': 3, 'd': 4, 'e': 2})
1 | x - y |
Counter({'d': 2})
1 | x & y |
Counter({'a': 1, 'd': 1})
1 | x | y |
Counter({'a': 2, 'd': 3, 'e': 2})
1 | # 仅在python3支持 |
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-35-a5890c994b78> in <module>()
1 # 仅在python3支持
----> 2 +x
TypeError: bad operand type for unary +: 'Counter'
有序字典——orderedDict
使用dict时,Key是无序的。在对dict做迭代时,我们无法确定Key的顺序。如果要保持Key的顺序,可以用OrderedDict
1 | from collections import OrderedDict |
1 | od = OrderedDict() |
a 1
c 1
b 2
默认类型字典——defaultdict
class collections.defaultdict([default_factory[, ...]])¶
使用dict时,如果引用的Key不存在,就会抛出KeyError。如果希望key不存在时,为key设置一个默认值,就可以用defaultdict。
1 | from collections import defaultdict |
如果我们想从无到有构建一个字典{key:list},通常有以下三种方式,可以看到使用defaultdict用时最少。
1 | # 使用get追加的方式最慢,因为每次都生成新的副本,O(n) |
值得注意的是,一旦我们引用了defaultdict中的某个key,defaultdict就会自动添加该key并为之赋予对应类型的默认值,因此使用x in dict时要格外注意:
1 | x = collections.defaultdict(int) |