python之collections

Collections

Python collections模块是一个非常实用且高效的模块,今天我们就来一起探索。

Counter

Counter是一个简单的计数器,传入的Counter的对象可以为字符串,list或者dict,返回的Counter对象对字符串,list或者dict里的元素进行简单的计数。

1
2
3
4
5
6
7
8
>>> Counter('helloworld!')
Counter({'l': 3, 'o': 2, '!': 1, 'e': 1, 'd': 1, 'h': 1, 'r': 1, 'w': 1})

>>> Counter(['Tom', 'Jerry', 'Tom', 'Alice'])
Counter({'Tom': 2, 'Jerry': 1, 'Alice': 1})

>>> Counter({'cat': 2, 'dog': 4})
Counter({'dog': 4, 'cat': 2})

可以看到,一个Counter对象是字典的一个子类,传入任意iterable时,会按key出现次数的顺序对Counter对象里的元素排序。当访问元素的时候,如果引用的key不存在于字典中,不会弹出keyerror而是返回0。

1
2
3
>>> c = Counter({'cat': 2, 'dog': 4})
>>> c['duck']
0

此外,Counter对象还有一些常用的方法

  • elements()
1
2
3
>>> c = Counter('helloworld!')
>>> list(c.elements())
['!', 'e', 'd', 'h', 'l', 'l', 'l', 'o', 'o', 'r', 'w']

该方法返回Counter中的所有key,按照一定顺序排序

  • most_common()
1
2
>>> Counter('dsfhbfshddas').most_common(3)
[('d', 3), ('s', 3), ('f', 2)]

该方法返回Counter中出现次数最多的k个(key, value) pair对

deque

list对象通过索引访问元素的时间复杂度为O(1),但是append和pop操作只能从尾部进行,当数据量很大时,我们想对头部元素进行操作时就会很耗时。deque是Collections模块里一个双向队列,支持从两端pop或者append元素,且两端的时间开销都为O(1)

deque对象支持从list或者字符串创建

1
2
>>> deque('abcde')
deque(['a', 'b', 'c', 'd', 'e'])
  • append, appendleft
1
2
3
4
5
>>> d = deque('bcde')
>>> d.append('f')
deque(['b', 'c', 'd', 'e', 'f'])
>>> d.appendleft('a')
deque(['a', 'b', 'c', 'd', 'e', 'f'])
  • pop, popleft
1
2
3
4
5
6
7
>>> d = deque('bcde')
>>> d.pop()
'e'
>>> d.popleft()
'b'
>>> d
deque(['c', 'd'])
  • extend, extendleft
1
2
3
4
5
>>> d = deque('cde')
>>> d.extend('fgh')
deque(['c', 'd', 'e', 'f', 'g', 'h'])
>>> d.extendleft('ab')
deque(['b', 'a', 'c', 'd', 'e', 'f', 'g', 'h'])

可见,在extendleft方法中,iterable参数中的顺序将被反过来添加。

  • rotate
1
2
3
4
5
>>> d = deque('cde')
>>> d.rotate(2) # right rotation
deque(['d', 'e', 'c'])
>>> d.rotate(-1) # left rotation
deque(['e', 'c', 'd'])

namedtuple

namedtuple用来创建自定义的tuple对象,支持用属性和索引访问tuple里的元素

1
2
3
4
5
6
7
>>> clock = namedtuple('clock', ['hour', 'minute', 'second'])
>>> t1 = clock(12, 0, 0) # 12点0分0秒
clock(hour=12, minute=0, second=0)
>>> t1.hour
12
>>> t1[0]
12

我们用namedtuple很方便地定义了一种时钟类型的数据结构,且具有tuple的不变形,十分好用

OrderedDict

我们在使用dict时,key是无序的,因此在遍历dict的过程中无法确定key的顺序

1
2
>>> d = {'b': 2, 'a': 1, 'c': 3}
{'a': 1, 'c': 3, 'b': 2}

要确定key的顺序可以使用OrderedDict,它会按照插入key的顺序排列,注意不是key本身的顺序

1
2
3
4
>>> d = OrderedDict([('b', 2), ('a', 1), ('c', 3)])
OrderedDict([('b', 2), ('a', 1), ('c', 3)])
>>> d['d'] = 5
OrderedDict([('b', 2), ('a', 1), ('c', 3), ('d', 5)])

此外,新版OrderedDict还支持key顺序移动

1
2
3
4
5
>>> d = OrderedDict.fromkeys('abcde')
OrderedDict([('a', None), ('b', None), ('c', None), ('d', None), ('e', None)])
>>> d.move_to_end('b') # 将b移动到末尾
>>> "".join(d.keys())
'acdeb'
休息一下,喝杯咖啡,继续创作