collections模块是python内置的模块。本模块主要有两方面的重要作用,第一方面是提供了一些特殊的容器类数据类型,作为Python原有的tuple, list , set, dict这些基础数据类型的扩充。第二方面是提供一系列的ABC(Abstract Base Class)以用来在编程时测试具体的对象。本文只探讨第一方面扩展的数据类型中的namedtuple(), deque 和 Counter。
这些扩展的特殊数据类型,与原生的数据类型相比,提供更加复杂实用的数据结构,具体见下表:
类型 | 英文解释 | 中文释义 |
namedtuple() | factory function for creating tuple subclasses with named fields | 带名字域的元组 |
deque | list-like container with fast appends and pops on either end | 具有队列功能的列表 |
ChainMap | dict-like class for creating a single view of multiple mappings | 提供多重映射的字典 |
Counter | dict subclass for counting hashable objects | 继承自字典类型,可用于计算可哈希的对象 |
OrderedDict | dict subclass that remembers the order entries were added | 继承自字典类型,但保留字典元素添加时的顺序 |
defaultdict | dict subclass that calls a factory function to supply missing values | 继承自字典类型,能按照设定创建默认的值类型 |
UserDict | wrapper around dictionary objects for easier dict subclassing | 为了更方便的创建字典子类而创建的Wrapper |
UserList | wrapper around list objects for easier list subclassing | 为了更方便的创建列表子类而创建的Wrapper |
UserString | wrapper around string objects for easier string subclassing | 为了更方便的创建字符串子类而创建的Wrapper |
1,namedtuple()
严格来讲,可以认为namedtuple是一个函数,用于构造带名字域的元组类型。
对于python原生的元组,有时候我们希望能对每个元组元素命名,这样方便阅读和管理。譬如,对如下一个表示一支股票股票数据
stock = ('顺丰控股', '002352', 51.72, -0.67, 331)
各个数据域的具体含义不是那么明显的,这时我们就可以使用namedtuple()函数来创建带名字域的元组,具体方法如下:
1 #使用Python3
2 from collections import namedtuple
3
4 stock = ('顺丰控股', '002352', 51.72, -0.67, 331)
5 Stock = namedtuple('Stock', ['name', 'id', 'price','change_pct','volume'])
6 s1 = Stock(*stock)
7 print(s1)
8
9
运行结果如下:
Stock(name='顺丰控股', id='002352', price=51.72, change_pct=-0.67, volume=331)
是不是一目了然?
代码里第3行调用了namedtuple函数,生成了一个名为Stock的带名字域的元组类型。namedtuple这个函数有两个输入参数,一个为新元组的类型名,一个为新元组名字域列表,即每个元组元素的名字,此处是通过一个含有5个名字的列表传递进来的。此句实际生成了Stock这种新的数据类型。
当我们创建具体的Stock类型的命名元组时,需要跟他传入5个位置参数。这就是第4行我们做的事情。最后打印出来后,我们能清晰的看到每个数据域以及其对应的名字。
2,deque
deque 用来创建一个先进先出(FIFO)的队列。使用时,一般先定义一个deque的对象,定义时需要设定maxlen值,也就是队列的长度,此后通过append方法添加元素,当添加的元素超过maxlen时,则自动将最先添加的元素出队,添加新的元素到队尾。
例如:
1 from collections import deque 2 3 que = deque(maxlen = 5) 4 for i in range(1,10) 5 que.append(i) 6 print(que)
运行结果如下:
deque([1], maxlen=5) deque([1, 2], maxlen=5) deque([1, 2, 3], maxlen=5) deque([1, 2, 3, 4], maxlen=5) deque([1, 2, 3, 4, 5], maxlen=5) deque([2, 3, 4, 5, 6], maxlen=5) deque([3, 4, 5, 6, 7], maxlen=5) deque([4, 5, 6, 7, 8], maxlen=5) deque([5, 6, 7, 8, 9], maxlen=5)
从运行结果,可以很清晰的看到队列的变化。
3,ChainMap
ChainMap 可以捆绑多个独立的映射关系成逻辑上的单个映射关系。这里的映射关系,是指python里表达映射关系的数据结构,最简单的,字典就是一个映射关系。具体用法如下:
1 a = {"a":1, "b":2, "c":3} 2 b = {"d":4, "e":5, "f":6} 3 c = {"g":7, "h":8, "i":9} 4 s = ChainMap(a, b , c)
这时候,字典a,b,c 上的每个元素都能从s访问到,如下
s['a'] Out[108]: 1 s['d'] Out[109]: 4 s['g'] Out[110]: 7
特别的,如果字典a,b,c中有重复的key值的话,s返回在构建ChainMap中先出现的字典key值
4,Counter
Counter是用于提供计数功能的字典类型容器。它能对特定的序列实现计数功能,并返回一个字典类型的结果,记录每个元素的计数值。举个例子:
1 l = ['a','b','c','d','e','a','b','c','d','e','a','b','c','f','g','h'] 2 cl = Counter(l) 3 cl 4 5 # output: 6 Counter({'a': 3, 'b': 3, 'c': 3, 'd': 2, 'e': 2, 'f': 1, 'g': 1, 'h': 1})
可以看到,Counter计算出了列表l中每个特定元素的个数。相应的,Counter也可以计算出字符串中每个特定字符的重复次数。
Counter还有几个非常有用的方法,比如keys和most_common。keys方法返回所有的key值,这个方法实际上可以帮助我们给序列去重。most_common方法接受一个整数参数i,返回前i个重复次数最多的元素,例如:
1 cl.keys() 2 # output 3 dict_keys(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
4 cl.most_common(2) 5 # output 6 [('a', 3), ('b', 3)]
注意,Counter要求被计数的序列元素必须是可哈希的,比如如果某个序列的元素是字典,则运用Counter就无法统计出该序列中特定元素的个数。