Python的collections模块真的很好用


Posted in Python onMarch 01, 2021

collections是实现了特定目标的容器,以提供Python标准内建容器 dict , list , set , 和 tuple 的替代选择。为了让大家更好的认识,本文详细总结collections的相关知识,一起来学习吧!

Python的collections模块真的很好用

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

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

使用 set 作为 default_factory

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

## OrderedDict

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

collections.OrderedDict 类提供了保留他们添加顺序的字典对象。

```python
>>> o = collections.OrderedDict()
>>> o['k1'] = 'v1'
>>> o['k3'] = 'v3'
>>> o['k2'] = 'v2'
>>> o
OrderedDict([('k1', 'v1'), ('k3', 'v3'), ('k2', 'v2')])

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

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

## namedtuple

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

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

实例化命名元组

```python
>>> 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。

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

```python
>>> 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
</code></pre>

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

<pre><code class="language-python line-numbers">>>> 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 是去掉了列表开头的元素。

```python
>>> 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 相关文章推荐
windows下python模拟鼠标点击和键盘输示例
Feb 28 Python
Python的__builtin__模块中的一些要点知识
May 02 Python
python自动翻译实现方法
May 28 Python
Python中return self的用法详解
Jul 27 Python
在python中pandas的series合并方法
Nov 12 Python
Django框架中间件(Middleware)用法实例分析
May 24 Python
通过pycharm使用git的步骤(图文详解)
Jun 13 Python
torch 中各种图像格式转换的实现方法
Dec 26 Python
PyTorch中 tensor.detach() 和 tensor.data 的区别详解
Jan 06 Python
Python pip安装模块提示错误解决方案
May 22 Python
教你怎么用python爬取爱奇艺热门电影
May 20 Python
python 爬取京东指定商品评论并进行情感分析
May 27 Python
Python  Asyncio模块实现的生产消费者模型的方法
Mar 01 #Python
Python创建自己的加密货币的示例
Mar 01 #Python
python 实现网易邮箱邮件阅读和删除的辅助小脚本
Mar 01 #Python
详解Django中的FBV和CBV对比分析
Mar 01 #Python
Python3压缩和解压缩实现代码
Mar 01 #Python
python re模块常见用法例举
Mar 01 #Python
Python实现简单的2048小游戏
Mar 01 #Python
You might like
php的$_FILES的临时储存文件与回收机制实测过程
2013/07/12 PHP
PHP中判断变量为空的几种方法小结
2013/11/12 PHP
php防止网站被刷新的方法汇总
2014/12/01 PHP
再谈PHP中单双引号的区别详解
2016/06/12 PHP
php批量删除操作代码分享
2017/02/26 PHP
jquery 插件学习(一)
2012/08/06 Javascript
前台js对象在后台转化java对象的问题探讨
2013/12/20 Javascript
jQuery瀑布流插件Wookmark使用实例
2014/04/02 Javascript
js onmousewheel事件多次触发问题解决方法
2014/10/17 Javascript
jquery实现搜索框常见效果的方法
2015/01/22 Javascript
JS获得图片alt信息的方法
2015/04/01 Javascript
实现前后端数据交互方法汇总
2015/04/07 Javascript
Js+Ajax,Get和Post在使用上的区别小结
2016/06/08 Javascript
Bootstrap中的表单验证插件bootstrapValidator使用方法整理(推荐)
2016/06/21 Javascript
jQuery实现在新增加的元素上添加事件方法案例分析
2017/02/09 Javascript
深入理解Webpack 中路径的配置
2017/06/17 Javascript
JavaScript ES6中const、let与var的对比详解
2017/06/18 Javascript
node.js + socket.io 实现点对点随机匹配聊天
2017/06/30 Javascript
vue.js内部自定义指令与全局自定义指令的实现详解(利用directive)
2017/07/11 Javascript
angularJs提交文本框数据到后台的方法
2018/10/08 Javascript
[01:09]DOTA2次级职业联赛 - 99战队宣传片
2014/12/01 DOTA
python使用新浪微博api上传图片到微博示例
2014/01/10 Python
python编程之requests在网络请求中添加cookies参数方法详解
2017/10/25 Python
Python多个装饰器的调用顺序实例解析
2020/05/22 Python
Pycharm插件(Grep Console)自定义规则输出颜色日志的方法
2020/05/27 Python
pytho matplotlib工具栏源码探析一之禁用工具栏、默认工具栏和工具栏管理器三种模式的差异
2021/02/25 Python
CSS3教程(5):网页背景图片
2009/04/02 HTML / CSS
Staples加拿大官方网站:办公用品一站式采购
2016/09/25 全球购物
18-35岁旅游团的全球领导者:Contiki
2017/02/08 全球购物
英国最大的割草机购买网站:Just Lawnmowers
2019/11/02 全球购物
大学生创业项目方案
2014/03/08 职场文书
公司授权委托书范文
2014/08/02 职场文书
借款协议书
2014/09/16 职场文书
2015年妇联工作总结范文
2015/04/22 职场文书
旅行社计调工作总结
2015/08/12 职场文书
Python办公自动化解决world文件批量转换
2021/09/15 Python