Python语言深入:collections模块深入(1)

    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就无法统计出该序列中特定元素的个数。

posted @ 2018-03-11 21:49  AlexDuval  阅读(178)  评论(0编辑  收藏  举报