Python collections模块的使用方法


Posted in Python onOctober 09, 2020

collections模块

这个模块实现了特定目标的容器,以提供Python标准内建容器 dict、list、set、tuple 的替代选择。

  • Counter:字典的子类,提供了可哈希对象的计数功能
  • defaultdict:字典的子类,提供了一个工厂函数,为字典查询提供了默认值
  • OrderedDict:字典的子类,保留了他们被添加的顺序
  • namedtuple:创建命名元组子类的工厂函数
  • deque:类似列表容器,实现了在两端快速添加(append)和弹出(pop)
  • ChainMap:类似字典的容器类,将多个映射集合到一个视图里面

Counter

Counter是一个dict子类,主要是用来对你访问的对象的频率进行计数。

>>> import collections
>>> # 统计字符出现的次数
... collections.Counter('hello world')
Counter({'l': 3, 'o': 2, 'h': 1, 'e': 1, ' ': 1, 'w': 1, 'r': 1, 'd': 1})
>>> # 统计单词个数
... collections.Counter('hello world hello lucy'.split())
Counter({'hello': 2, 'world': 1, 'lucy': 1})

常用方法:

  • elements():返回一个迭代器,每个元素重复计算的个数,如果一个元素的计数小于1,就会被忽略
  • most_common([n]):返回一个列表,提供n个访问频率最高的元素和计数
  • subtract([iterable-or-mapping]):从迭代对象中减去元素,输入输出可以是0或者负数
  • update([iterable-or-mapping]):从迭代对象计数元素或者从另一个 映射对象 (或计数器) 添加
>>> c = collections.Counter('hello world hello lucy'.split())
>>> c
Counter({'hello': 2, 'world': 1, 'lucy': 1})
>>> # 获取指定对象的访问次数,也可以使用get方法
... c['hello']
2
>>> # 查看元素
... list(c.elements())
['hello', 'hello', 'world', 'lucy']
>>> c1 = collections.Counter('hello world'.split())
>>> c2 = collections.Counter('hello lucy'.split())
>>> c1
Counter({'hello': 1, 'world': 1})
>>> c2
Counter({'hello': 1, 'lucy': 1})
>>> # 追加对象,+或者c1.update(c2)
... c1+c2
Counter({'hello': 2, 'world': 1, 'lucy': 1})
>>> # 减少对象,-或者c1.subtract(c2)
... c1-c2
Counter({'world': 1})
>>> # 清除
... c.clear()
>>> c
Counter()

defaultdict

返回一个新的类似字典的对象。 defaultdict 是内置 dict 类的子类。

class collections.defaultdict([default_factory[, ...]])
>>> d = collections.defaultdict()
>>> d
defaultdict(None, {})
>>> e = collections.defaultdict(str)
>>> e
defaultdict(<class 'str'>, {})

例子

defaultdict的一个典型用法是使用其中一种内置类型(如str、int、list或dict等)作为默认工厂,这些内置类型在没有参数调用时返回空类型。

>>> e = collections.defaultdict(str)
>>> e
defaultdict(<class 'str'>, {})
>>> e['hello']
''
>>> e
defaultdict(<class 'str'>, {'hello': ''})
>>> # 普通字典调用不存在的键时,报错
... e1 = {}
>>> e1['hello']
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
KeyError: 'hello'

使用 int 作为 default_factory

>>> fruit = collections.defaultdict(int)
>>> fruit['apple'] = 2
>>> fruit
defaultdict(<class 'int'>, {'apple': 2})
>>> fruit['banana'] # 没有对象时,返回0
0
>>> fruit
defaultdict(<class 'int'>, {'apple': 2, 'banana': 0})

使用 list 作为 default_factory

>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = collections.defaultdict(list)
>>> for k,v in s:
...   d[k].append(v)
...
>>> d
defaultdict(<class 'list'>, {'yellow': [1, 3], 'blue': [2, 4], 'red': [1]})
>>> d.items()
dict_items([('yellow', [1, 3]), ('blue', [2, 4]), ('red', [1])])
>>> sorted(d.items())
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

使用 dict 作为 default_factory

>>> nums = collections.defaultdict(dict)
>>> nums[1] = {'one':1}
>>> nums
defaultdict(<class 'dict'>, {1: {'one': 1}})
>>> nums[2]
{}
>>> nums
defaultdict(<class 'dict'>, {1: {'one': 1}, 2: {}})

使用 set 作为 default_factory

>>> types = collections.defaultdict(set)
>>> types['手机'].add('华为')
>>> types['手机'].add('小米')
>>> types['显示器'].add('AOC')
>>> types
defaultdict(<class 'set'>, {'手机': {'华为', '小米'}, '显示器': {'AOC'}})

 OrderedDict

Python字典中的键的顺序是任意的,它们不受添加的顺序的控制。

collections.OrderedDict 类提供了保留他们添加顺序的字典对象
>>> o = collections.OrderedDict()
>>> o['k1'] = 'v1'
>>> o['k3'] = 'v3'
>>> o['k2'] = 'v2'
>>> o
OrderedDict([('k1', 'v1'), ('k3', 'v3'), ('k2', 'v2')])

如果在已经存在的 key 上添加新的值,将会保留原来的 key 的位置,然后覆盖 value 值。

>>> o['k1'] = 666
>>> o
OrderedDict([('k1', 666), ('k3', 'v3'), ('k2', 'v2')])
>>> dict(o)
{'k1': 666, 'k3': 'v3', 'k2': 'v2'}

namedtuple

三种定义命名元组的方法:第一个参数是命名元组的构造器(如下的:Person1,Person2,Person3)

>>> P1 = collections.namedtuple('Person1',['name','age','height'])
>>> P2 = collections.namedtuple('Person2','name,age,height')
>>> P3 = collections.namedtuple('Person3','name age height')

实例化命名元组

>>> lucy = P1('lucy',23,180)
>>> lucy
Person1(name='lucy', age=23, height=180)
>>> jack = P2('jack',20,190)
>>> jack
Person2(name='jack', age=20, height=190)
>>> lucy.name # 直接通过 实例名.属性 来调用
'lucy'
>>> lucy.age
23

deque

collections.deque 返回一个新的双向队列对象,从左到右初始化(用方法 append()),从 iterable(迭代对象)数据创建。如果 iterable 没有指定,新队列为空。
collections.deque 队列支持线程安全,对于从两端添加(append)或者弹出(pop),复杂度O(1)。
 虽然 list 对象也支持类似操作,但是这里优化了定长操作(pop(0)、insert(0,v))的开销。
 如果 maxlen 没有指定或者是 None ,deque 可以增长到任意长度。否则,deque 就限定到指定最大长度。一旦限定长度的 deque 满了,当新项加入时,同样数量的项就从另一端弹出。

支持的方法:

  • append(x):添加x到右端
  • appendleft(x):添加x到左端
  • clear():清除所有元素,长度变为0
  • copy():创建一份浅拷贝
  • count(x):计算队列中个数等于x的元素
  • extend(iterable):在队列右侧添加iterable中的元素
  • extendleft(iterable):在队列左侧添加iterable中的元素,注:在左侧添加时,iterable参数的顺序将会反过来添加
  • index(x[,start[,stop]]):返回第 x 个元素(从 start 开始计算,在 stop 之前)。返回第一个匹配,如果没找到的话,升起 ValueError 。
  • insert(i,x):在位置 i 插入 x 。注:如果插入会导致一个限长deque超出长度 maxlen 的话,就升起一个 IndexError 。
  • pop():移除最右侧的元素
  • popleft():移除最左侧的元素
  • remove(value):移去找到的第一个 value。没有抛出ValueError
  • reverse():将deque逆序排列。返回 None 。
  • maxlen:队列的最大长度,没有限定则为None。
>>> d = collections.deque(maxlen=10)
>>> d
deque([], maxlen=10)
>>> d.extend('python')
>>> [i.upper() for i in d]
['P', 'Y', 'T', 'H', 'O', 'N']
>>> d.append('e')
>>> d.appendleft('f')
>>> d.appendleft('g')
>>> d.appendleft('h')
>>> d
deque(['h', 'g', 'f', 'p', 'y', 't', 'h', 'o', 'n', 'e'], maxlen=10)
>>> d.appendleft('i')
>>> d
deque(['i', 'h', 'g', 'f', 'p', 'y', 't', 'h', 'o', 'n'], maxlen=10)
>>> d.append('m')
>>> d
deque(['h', 'g', 'f', 'p', 'y', 't', 'h', 'o', 'n', 'm'], maxlen=10)

ChainMap

问题背景是我们有多个字典或者映射,想把它们合并成为一个单独的映射,有人说可以用update进行合并,这样做的问题就是新建了一个数据结构以致于当我们对原来的字典进行更改的时候不会同步。如果想建立一个同步的查询方法,可以使用 ChainMap

可以用来合并两个或者更多个字典,当查询的时候,从前往后依次查询。简单使用:

>>> d1 = {'apple':1,'banana':2}
>>> d2 = {'orange':2,'apple':3,'pike':1}
>>> combined1 = collections.ChainMap(d1,d2)
>>> combined2 = collections.ChainMap(d2,d1)
>>> combined1
ChainMap({'apple': 1, 'banana': 2}, {'orange': 2, 'apple': 3, 'pike': 1})
>>> combined2
ChainMap({'orange': 2, 'apple': 3, 'pike': 1}, {'apple': 1, 'banana': 2})
>>> for k,v in combined1.items():
...   print(k,v)
...
orange 2
apple 1
pike 1
banana 2
>>> for k,v in combined2.items():
...   print(k,v)
...
apple 3
banana 2
orange 2
pike 1

有一个注意点就是当对ChainMap进行修改的时候总是只会对第一个字典进行修改,如果第一个字典不存在该键,会添加。

>>> d1 = {'apple':1,'banana':2}
>>> d2 = {'orange':2,'apple':3,'pike':1}
>>> c = collections.ChainMap(d1,d2)
>>> c
ChainMap({'apple': 1, 'banana': 2}, {'orange': 2, 'apple': 3, 'pike': 1})
>>> c['apple']
1
>>> c['apple'] = 2
>>> c
ChainMap({'apple': 2, 'banana': 2}, {'orange': 2, 'apple': 3, 'pike': 1})
>>> c['pike']
1
>>> c['pike'] = 3
>>> c
ChainMap({'apple': 2, 'banana': 2, 'pike': 3}, {'orange': 2, 'apple': 3, 'pike': 1})

从原理上面讲,ChainMap 实际上是把放入的字典存储在一个队列中,当进行字典的增加删除等操作只会在第一个字典上进行,当进行查找的时候会依次查找,new_child() 方法实质上是在列表的第一个元素前放入一个字典,默认是{},而 parents 是去掉了列表开头的元素

>>> a = collections.ChainMap()
>>> a['x'] = 1
>>> a
ChainMap({'x': 1})
>>> b = a.new_child()
>>> b
ChainMap({}, {'x': 1})
>>> b['x'] = 2
>>> b
ChainMap({'x': 2}, {'x': 1})
>>> b['y'] = 3
>>> b
ChainMap({'x': 2, 'y': 3}, {'x': 1})
>>> a
ChainMap({'x': 1})
>>> c = a.new_child()
>>> c
ChainMap({}, {'x': 1})
>>> c['x'] = 1
>>> c['y'] = 1
>>> c
ChainMap({'x': 1, 'y': 1}, {'x': 1})
>>> d = c.parents
>>> d
ChainMap({'x': 1})
>>> d is a
False
>>> d == a
True
>>> a = {'x':1,'z':3}
>>> b = {'y':2,'z':4}
>>> c = collections.ChainMap(a,b)
>>> c
ChainMap({'x': 1, 'z': 3}, {'y': 2, 'z': 4})
>>> c.maps
[{'x': 1, 'z': 3}, {'y': 2, 'z': 4}]
>>> c.parents
ChainMap({'y': 2, 'z': 4})
>>> c.parents.maps
[{'y': 2, 'z': 4}]
>>> c.parents.parents
ChainMap({})
>>> c.parents.parents.parents
ChainMap({})

到此这篇关于Python collections模块的使用方法的文章就介绍到这了,更多相关Python collections模块内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木! 

Python 相关文章推荐
python机器学习理论与实战(五)支持向量机
Jan 19 Python
python中join()方法介绍
Oct 11 Python
Python语法分析之字符串格式化
Jun 13 Python
Django框架orM与自定义SQL语句混合事务控制操作
Jun 27 Python
基于Django ORM、一对一、一对多、多对多的全面讲解
Jul 26 Python
浅析Python数字类型和字符串类型的内置方法
Dec 22 Python
通过 Python 和 OpenCV 实现目标数量监控
Jan 05 Python
利用Python制作动态排名图的实现代码
Apr 09 Python
Django Model层F,Q对象和聚合函数原理解析
Nov 12 Python
基于Django集成CAS实现流程详解
Nov 28 Python
基于Python的EasyGUI学习实践
May 07 Python
七个非常实用的Python工具包总结
Jun 15 Python
python爬取代理IP并进行有效的IP测试实现
Oct 09 #Python
Python中Selenium模块的使用详解
Oct 09 #Python
python利用platform模块获取系统信息
Oct 09 #Python
python smtplib发送多个email联系人的实现
Oct 09 #Python
python 决策树算法的实现
Oct 09 #Python
Python+unittest+requests 接口自动化测试框架搭建教程
Oct 09 #Python
Python实现http接口自动化测试的示例代码
Oct 09 #Python
You might like
php 验证码实例代码
2010/06/01 PHP
php的字符串用法小结
2010/06/08 PHP
php隐藏IP地址后两位显示为星号的方法
2014/11/21 PHP
在Win2003(64位)中配置IIS6+PHP5.2.17+MySQL5.5的运行环境
2016/04/04 PHP
phpcms的分类名称和类别名称的调用
2017/01/05 PHP
php实现将数组或对象写入到文件的方法小结【三种方法】
2020/04/22 PHP
定时器(setTimeout/setInterval)调用带参函数失效解决方法
2013/03/26 Javascript
JavaScript检测浏览器cookie是否已经启动的方法
2015/02/27 Javascript
JavaScript基于setTimeout实现计数的方法
2015/05/08 Javascript
JavaScript forEach()遍历函数使用及介绍
2015/07/08 Javascript
vue插件tab选项卡使用小结
2016/10/27 Javascript
jQuery移除或禁用html元素点击事件常用方法小结
2017/02/10 Javascript
Vue 短信验证码组件开发详解
2017/02/14 Javascript
一个有意思的鼠标点击文字特效jquery代码
2017/09/23 jQuery
vue组件name的作用小结
2018/05/23 Javascript
Vue3新特性之在Composition API中使用CSS Modules
2020/07/13 Javascript
vue实现lodop打印功能的示例
2020/11/11 Javascript
Python中使用Inotify监控文件实例
2015/02/14 Python
python绘图方法实例入门
2015/05/19 Python
Python实现按逗号分隔列表的方法
2018/10/23 Python
利用python求积分的实例
2019/07/03 Python
python使用openCV遍历文件夹里所有视频文件并保存成图片
2020/01/14 Python
关于win10在tensorflow的安装及在pycharm中运行步骤详解
2020/03/16 Python
html5之Canvas路径绘图、坐标变换应用实例
2012/12/26 HTML / CSS
幼教个人求职信范文
2013/12/02 职场文书
转让协议书范本
2014/04/15 职场文书
学雷锋活动总结范文
2014/04/25 职场文书
老公保证书范文
2014/04/29 职场文书
新农村建设汇报材料
2014/08/15 职场文书
党员干部四风问题整改措施思想汇报
2014/10/12 职场文书
2014年小学数学教师工作总结
2014/12/03 职场文书
高中团支书竞选稿
2015/11/21 职场文书
2020年元旦祝福语录,总有适合你的
2019/12/31 职场文书
PostgreSQL将数据加载到buffer cache中操作方法
2021/04/16 PostgreSQL
Vue过滤器(filter)实现及应用场景详解
2021/06/15 Vue.js
浅谈哪个Python库才最适合做数据可视化
2021/06/28 Python