python常用库之collections与itertools
最近看题解的时候发现好多问题可以直接使用内置库函数解决,及优雅又高效(开挂实锤)。下面依次来介绍这两个包的常见用法。
collections
collections
是Python内建的一个集合模块,提供了许多有用的集合类,这个模块实现了特定目标的容器,以提供Python标准内建容器 dict, list, set, 和 tuple的替代选择。相关连接:官方文档, 廖雪峰的python3教程。
namedtuple
这个是对tuple的扩展,namedtuple
是一个函数,它用来创建一个自定义的tuple
对象,并且规定了tuple元素的个数,并可以用属性而不是索引来引用tuple的某个元素。用例:
>>> from collections import namedtuple
# namedtuple('名称', [属性list]):
>>> Point = namedtuple('Point', ['x', 'y'])
>>> p = Point(1, 2)
>>> p.x
1
>>> p.y
2
namedtuple主要用于快速声明一个自定义tuple,避免创建class(完全可以用class代替)。其他具体用法见官方文档。
deque
在python中,数组对应着list。使用list
存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为list
是线性存储,数据量大的时候,插入和删除效率很低。deque
是为了高效实现插入和删除操作的双向列表,适合用于队列和栈。
>>> from collections import deque
>>> q = deque(['a', 'b', 'c'])
>>> q.append('x')
>>> q.appendleft('y')
>>> q
deque(['y', 'a', 'b', 'c', 'x'])
Deque队列是由栈或者queue队列生成的(发音是 “deck”,”double-ended queue”的简称)。Deque 支持线程安全,内存高效添加(append)和弹出(pop),从两端都可以,两个方向的大概开销都是 O(1) 复杂度。虽然 list
对象也支持类似操作,不过这里优化了定长操作和 pop(0)
和 insert(0, v)
的开销。它们引起 O(n) 内存移动的操作,改变底层数据表达的大小和位置。deque
除了实现list
的append()
和pop()
外,还支持appendleft()
和popleft()
,这样就可以非常高效地往头部添加或删除元素。
如果 maxlen 没有指定或者是 None
,deques 可以增长到任意长度。否则,deque就限定到指定最大长度。一旦限定长度的deque满了,当新项加入时,同样数量的项就从另一端弹出。限定长度deque提供类似Unix filter tail
的功能。它们同样可以用与追踪最近的交换和其他数据池活动。
defaultdict
使用dict
时,如果引用的Key
不存在,就会抛出KeyError
。如果希望key
不存在时,返回一个默认值,就可以用defaultdict
。defaultdict接受一个类型(其实是函数)作为输入,当访问的键不存在时,普通的dict会报错,而defaultdict就会自动创建该键并给出设定的类型的默认值。
eg1:
>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> for k, v in s:
d[k].append(v)
# 每个键在初次访问时都不存在,defaultdict会创建并默认给一个默认值(这里是[]),即d[k]为list
>>> sorted(d.items())
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]
eg2:
>>> from collections import defaultdict
>>> dd = defaultdict(lambda: 'N/A')
>>> dd['key1'] = 'abc'
>>> dd['key1'] # key1存在
'abc'
>>> dd['key2'] # key2不存在,返回默认值
'N/A'
这里传入的参数就是一个函数,默认返回“N/A”。
OrderedDict
使用dict
时,Key
是无序的。在对dict
做迭代时,我们无法确定Key
的顺序。如果要保持Key
的顺序,可以用OrderedDict
。
>>> from collections import OrderedDict
>>> d = dict([('a', 1), ('b', 2), ('c', 3)])
>>> d # dict的Key是无序的
{'a': 1, 'c': 3, 'b': 2}
>>> od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
>>> od # OrderedDict的Key是有序的
OrderedDict([('a', 1), ('b', 2), ('c', 3)])
需要注意的是,orderedDict中key的顺序是输入的顺序,并不是键值本身的顺序。另外有序字典的 popitem()
方法移除并返回一个 (key, value) 键值对。 如果 last 值为真,则按 LIFO 后进先出的顺序返回键值对,否则就按 FIFO 先进先出的顺序返回键值对(默认为True)。
Counter
Counter
是一个简单的计数器,例如,统计字符出现的个数。
>>> from collections import Counter
>>> c = Counter('programming')
>>> c
Counter({'g': 2, 'm': 2, 'r': 2, 'a': 1, 'i': 1, 'o': 1, 'n': 1, 'p': 1})
用处比较多,可以快速统计元素个数。输入参数是一个 iterable 被计数或其他的 mapping (or counter):即可。
需要注意的是:设置一个计数为0不会从计数器中移去一个元素。使用 del
来删除它,Counter对象有一个字典接口,如果引用的键没有任何记录,就返回一个0,而不是弹出一个 KeyError
。
itertools
Python的内建模块itertools
提供了非常有用的用于操作迭代对象的函数。
无限迭代器
无限迭代器创建一个迭代器,它从 start 值开始,返回均匀间隔的值。常用于 map()
中的实参来生成连续的数据点。此外,还用于 zip()
来添加序列号。itertools.count(start=0, step=1)
,