python中的collections
python中有大量的内置模块,很多是属于特定开发的功能性模块,但collections是属于对基础数据的类型的补充模块,因此,在日常代码中使用频率更高一些,值得做个笔记,本文只做主要关键字介绍,详细的功能仍然要翻阅官方文档,地址如下:
英文站:https://docs.python.org/3.5/library/collections.html
中文站:http://python.usyiyi.cn/translate/python_352/library/collections.html#module-collections
1. Counter
counter是属于字典的子类,主要作用是统计可哈希对象的个数,追踪元素出现的次数并按照从高到低的顺序排列成字典,对象为key,出现的次数为value。示例代码如下:
__author__ = "lixin" import collections #在使用的时候需要先导入collections模块 # counter 计数器 对字典的扩充 统计字符出现次数 需要用类生成对象 c1 = collections.Counter("arhshdgrgrgas")#生成一个Counter对象,追踪一个字符串 print(c1) print(c1.most_common(2))# 取前两个元素 """ 输出结果如下 /Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5 /Users/penglong/Documents/python/S11/day3/collection系列/lixin_collections.py Counter({'r': 3, 'g': 3, 'h': 2, 'a': 2, 's': 2, 'd': 1}) [('r', 3), ('g', 3)]
"""
如上,Counter的主要作用就是跟踪内容统计相同元素出现的次数并生成一个字典返回。在使用时首先要调用模块,再根据类生成对象,再使用。同时Counter内部提供了很多方法对结果进行处理,如most_common就是取字典里前两个元素,由于Counter的排列是从高到低,所以也可以说这是取出现次数最多的前俩元素
2.orderdictionary
orderdictionary是一个有序字典,python常用的字典类是没有顺序的,在有些情况下,我们可能需要跟踪到字典key值的添加先后顺序,如果自己去写实现过程,就需要数组和字典配合,而orderdictionary则把这个过程包装成了一个类,可以直接使用就行。代码如下:
#需要导入collections模块 此处是因为上面的代码已导入 orderdict = collections.OrderedDict() orderdict["k1"] = "test1" orderdict["k2"] = "test2" orderdict["k3"] = "test3" print(orderdict) common_dict = {} common_dict["k1"] = "test1" common_dict["k2"] = "test2" common_dict["k3"] = "test3" print(common_dict) """ 输出结果 /Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5 /Users/penglong/Documents/python/S11/day3/collection系列/lixin_collections.py 有序字典的结果:OrderedDict([('k1', 'test1'), ('k2', 'test2'), ('k3', 'test3')]) 无序字典的结果{'k3': 'test3', 'k1': 'test1', 'k2': 'test2'} """
如上,根据有序和无序字典的对比可以看到,orderdictionary的输出结果是按照我们的元素添加记录来排列的,而普通字典则没有这样的功能,这也是要注意的一点,orderdictionary记录的是添加顺序,而不是内部自身排序。
3.defaultdictionary
默认字典,为了精简代码的一个类,在处理一些数据的时候,我们可能要通过字典来存取,在不知道字典类型的时候,需要先给个判断才能调用相关类方法,因此,python给了一个封装,使我们在使用字典的时候可以指定字典的value类型,从而可以直接使用value内部元素的类方法。代码如下
#defaultdict 默认字典 让字典的值有默认类型,可以直接使用类方法 My_dict = collections.defaultdict(list)#指定字典value类型为list My_dict["k1"] = [5,6,89,30]#存一个键值对 My_dict["k1"].append(68)#直接调用list类方法 print(My_dict["k1"]) """ 输出结果 /Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5 /Users/penglong/Documents/python/S11/day3/collection系列/lixin_collections.py [5, 6, 89, 30, 68] """
对于默认字典而言,使用场景还是挺多的,尤其是在字典初始值为空的情况,如果是普通字典,在添加第一个value内部,我们往往需要特意注明格式,如果是默认字典,则可以避免这一代码流程
4.namedtuple
可命名元组,在这可以提到一下swift,siwft更新到3.0之后,语法标准是元组强制命名。但在python中,截止目前我使用3.5未知。仍然是可以自由定义元组,无需命名。但有些时候,我们需要用到可命名元组让别人知道这个数据结构的使用意义,如一个直角坐标系,最好表明第一个元素是X,第二个元素是Y。这种情况,python也无需再自己写新类,因为collections里面有一个可命名元组,使用代码如下
#namedtuple 可命名元组 必须先创建类 再根据类创建对象,再使用对象 如下例子 coordinae = collections.namedtuple("coordinate",["x","y"])#第一个参数为类名称,第二个为需要设置的参数名称 point = coordinae(3,5) #point = coordinae(x=3,y=5)#生成对象方法 print(point.x)#可命名元组除了方便说明数据结构意义,更多是为了方便调用,可以直接根据名称调用 print(point.y) base_tuple = (1,"lixin")#原始元组只能通过下标来访问 print(base_tuple[1]) """ /Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5 /Users/penglong/Documents/python/S11/day3/collection系列/lixin_collections.py 3 5 lixin """
5.deque
双向队列,为一个队列提供双向支持,并且默认线程安全,因此队列元素支持双向添加,并且双向可取,示例代码如下:
#双向队列 双头可取,线程安全 My_deque = collections.deque() #示例化一个双向队列对象 My_deque.append(12)#从右边添加一个元素 My_deque.appendleft(90)#从左边添加一个元素 My_deque.appendleft(80)#在从左边添加一个原 number = My_deque.pop()# pop默认是从右边获取,即12.pop不仅获取值,还会移除原来队列里的元素 print("右边第一个值为:",number) My_deque.popleft()#获取左边第一个值,同时也会移除相当于此时队列应该只剩下90这个元素 print(My_deque)#打印队列 """输出结果 /Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5 /Users/penglong/Documents/python/S11/day3/collection系列/lixin_collections.py 右边第一个值为:12 deque([90]) """
6.chainmaps
字面翻译,就是链条maps。在我的个人使用中,它更多用于多个字典更新循环迭代管理。当然官方文档给的作用远远不止于此。代码示例如下:
#chainmaps 链条map dict1 = {"a":1,"b":2} dict2 = {"c":3,"d":4}#生成俩个字典对象 chain = collections.ChainMap(dict1,dict2)#chain对象,把两个字典做为参数 print("旧的chain对象:",chain)#输出chain对象,输出结果是一个元组 print("maps方法调用:",chain.maps)#通过maps方法输出chain,结果是一个数组 print("maps下标取值",(chain.maps)[1])#因此我们可以通过下标调用 print("所有对象的key值",list(chain.keys()))#chain的作用,串联字典对象,统一执行命令,如获取key值 print("所有对象的value值:",list(chain.values()))#获取value值,python3.x中都需要list接受map展开对象 chain = chain.new_child({"e":5,"f":6})#添加一个新字典 print("新的chain对象:",chain)#重新打印一下值,输出结果如下 """输出结果 /Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5 /Users/penglong/Documents/python/S11/day3/collection系列/lixin_collections.py 旧的chain对象: ChainMap({'a': 1, 'b': 2}, {'c': 3, 'd': 4}) maps方法调用: [{'a': 1, 'b': 2}, {'c': 3, 'd': 4}] maps下标取值 {'c': 3, 'd': 4} 所有对象的key值 ['a', 'c', 'b', 'd'] 所有对象的value值: [1, 3, 2, 4] 新的chain对象: ChainMap({'f': 6, 'e': 5}, {'a': 1, 'b': 2}, {'c': 3, 'd': 4}) """
7.userdict,userlist,userstring
这三个类都属于collections模块,其作用有一定共性,都是对原始dict,list,string数据进行一份拷贝,生成新的数据进行额外处理。在实际使用中,接触不久,我暂时还没遇到,而且它的作用完全能被普通新对象代替。以userdict为例,实例代码如下:
d = {'a': 2, 'b': 3}#实例一个字典 ud = collections.UserDict(d)#user字典 print("d = %s ,ud = %s "%(d,ud))#打印俩对象 del ud['a']#删除ud字典中的一个元素 print("d = %s ,ud = %s "%(d,ud))#再次输出一下 """输出结果 d = {'a': 2, 'b': 3} ,ud = {'a': 2, 'b': 3} d = {'a': 2, 'b': 3} ,ud = {'b': 3} """
#如上,user本身还有个data属性,官方文档说是存储真正的数据。我尝试了去删除data里的数据,以为可以控制原字典对象,
然而并不能!so,我也不知道它存在的意义是什么。。 等知道了补充。
9。queue 队列补充,queue本身不属于collections模块,只是和双向队列比较一下
除了双向队列,自然还有单项队列。但单向队列属于queue模块。在python 2.x版本这个模块是Queue。单项队列在python中又分为队列和栈两种形式。队列的特点是先进先出,如果在队列中没有元素的情况下强行获取,则堵塞程序,直到队列中有元素可取。栈属于后进先出。两个类的拿去方法都是一样的,所以示例代码放在一起做个对比,如下:
__author__ = "lixin" import queue#queue并不包括在collections模块以内,需要另外导入 #单向队列 让消费者等待 直到队列里有元素可取 优先级队列未举例子喔 one = queue.Queue()#生成队列 先进先出 one.put(20)#放入一个数字 one.put(80) print("队列的输出结果:",one.get())#拿到的是20 two = queue.LifoQueue()#生成一个栈 后进先出 two.put(20) two.put(80) print("栈的输出结果:",two.get())#拿到的是80 """输出结果 /Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5 /Users/penglong/Documents/python/S11/day3/collection系列/lixin_collections.py 队列的输出结果: 20 栈的输出结果: 80 """
如上,python的collections大多是对一些常用类的扩充,有许多功能可以让我们实现一些自定义功能而不必额外添加代码,属于加分技能,但由于使用频率,我不敢说通透,所以如果想要得心应手,建议还是仔细阅读一下官方文档。文章仅作笔记。