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 相关文章推荐
Web服务器框架 Tornado简介
Jul 16 Python
Python合并字符串的3种方法
May 21 Python
Python检测字符串中是否包含某字符集合中的字符
May 21 Python
快速了解python leveldb
Jan 18 Python
Python读取Word(.docx)正文信息的方法
Mar 15 Python
Python中垃圾回收和del语句详解
Nov 15 Python
Python 开发工具PyCharm安装教程图文详解(新手必看)
Feb 28 Python
Python爬虫爬取新闻资讯案例详解
Jul 14 Python
python实现简单的tcp 文件下载
Sep 16 Python
Python面向对象多态实现原理及代码实例
Sep 16 Python
python3访问字典里的值实例方法
Nov 18 Python
python基于爬虫+django,打造个性化API接口
Jan 21 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
实用函数7
2007/11/08 PHP
PHP 根据IP地址控制访问的代码
2010/04/22 PHP
PHP输出英文时间日期的安全方法(RFC 1123格式)
2014/06/13 PHP
js中将字符串转换成json的三种方式
2011/01/12 Javascript
jQuery读取和设定KindEditor值的方法
2013/11/22 Javascript
javascript基于HTML5 canvas制作画箭头组件
2014/06/25 Javascript
javascript实现点击提交按钮后显示loading的方法
2015/07/03 Javascript
Bootstrap每天必学之导航
2015/11/26 Javascript
谈谈基于iframe、FormData、FileReader三种无刷新上传文件的方法
2015/12/03 Javascript
jQuery模仿阿里云购买服务器选择购买时间长度的代码
2016/04/29 Javascript
详解Jquery EasyUI tree 的异步加载(遍历指定文件夹,根据文件夹内的文件生成tree)
2017/02/11 Javascript
详解Angular Reactive Form 表单验证
2017/07/06 Javascript
详解Vue路由History mode模式中页面无法渲染的原因及解决
2017/09/28 Javascript
vue实现图片上传预览功能
2019/12/23 Javascript
浅析vue-router实现原理及两种模式
2020/02/11 Javascript
[02:30]DOTA2英雄基础教程 暗影恶魔
2013/12/17 DOTA
python获取mp3文件信息的方法
2015/06/15 Python
Django的URLconf中使用缺省视图参数的方法
2015/07/18 Python
浅谈python requests 的put, post 请求参数的问题
2019/01/02 Python
python实现发送form-data数据的方法详解
2019/09/27 Python
浅谈keras中的目标函数和优化函数MSE用法
2020/06/10 Python
Python基于opencv的简单图像轮廓形状识别(全网最简单最少代码)
2021/01/28 Python
Python就将所有的英文单词首字母变成大写
2021/02/12 Python
CSS3属性box-shadow使用详细教程
2012/01/21 HTML / CSS
css3 线性渐变和径向渐变示例附图
2014/04/08 HTML / CSS
把富文本的回车转为br标签
2019/08/09 HTML / CSS
华为俄罗斯官方网上商城:购买Huawei手机和平板
2017/04/21 全球购物
巴西男士胡须和头发护理产品商店:Beard
2017/11/13 全球购物
美国领先的眼镜和太阳镜在线零售商:Glasses.com
2019/08/26 全球购物
牵手50台湾:专为黄金岁月的单身人士而设的交友网站
2021/02/18 全球购物
线程的基本概念、线程的基本状态以及状态之间的关系
2012/10/26 面试题
Linux机考试题
2015/07/17 面试题
国际贸易个人求职信范文
2014/01/04 职场文书
报关员个人职业生涯规划书
2014/03/12 职场文书
保险公司反洗钱宣传活动总结
2015/05/08 职场文书
2015秋季幼儿园开学通知
2015/07/16 职场文书