详解Python 中的容器 collections


Posted in Python onAugust 17, 2020

写在之前

我们都知道 Python 中内置了许多标准的数据结构,比如列表,元组,字典等。与此同时标准库还提供了一些额外的数据结构,我们可以基于它们创建所需的新数据结构。

Python 附带了一个「容器」模块 collections,它包含了很多的容器数据类型,今天我们来讨论其中几个常用的容器数据类型,掌握了这几个可以减少我们重复造轮子所带来的烦扰。

namedtuple

相信你已经熟悉了元组。一个元组相当于一个不可变的列表,你可以存储一个数据的序列。这里要说的 namedtuple(命名元组)和元组非常像,它们都不能修改自己的数据。说完了像,那么它们有哪些地方不像呢?

作为元组,为了获取其中的数据,我们需要使用整数作为索引:

>>> people = ('Rocky', 'python')
>>> print(people[0])
Rocky

而 namedtuple 把元组变成了一个针对简单任务的容器,我们不必使用整数索引来访问 namedtuple 的数据,反而可以像用字典一样访问 namedtuple。

>>> from collections import namedtuple
>>> people = namedtuple('people', 'name age like')
>>> Rocky = people(name = 'rocky', age = 23, like = 'python')
>>> print(Rocky)
people(name='rocky', age=23, like='python')
>>> print(Rocky.name)
rocky

一个 namedtuple 有两个必须的参数:元组名称和字段名称。在上面的代码中,我们的元组名称是 people,字段名称是 name,age,like。nametuple 让元组变的更加易读,很容易理解代码是做什么的,同样我们也不用使用整数索引来访问一个命名元组(上面代码我们用 name 访问了 namedtuple 中的数据),这让我们的代码更加容易维护。

但是你一定要记住的是,虽然它的用法很爽,但它还是一个元组!所以属性值在 namedtuple 中是不可变的。

我们在上面说过可以像用字典一样访问 namedtuple,那么当然也可以把它转为字典,具体操作如下所示:

>>> from collections import namedtuple
>>> people = namedtuple('people', 'name age like')
>>> Rocky = people(name = 'rocky', age = 23, like = 'python')
>>> print(Rocky._asdict())
OrderedDict([('name', 'rocky'), ('age', 23), ('like', 'python')])

defaultdict

我之前在使用字典的时候相当随意,只是随便 dict 一下就好了,然而这样使用存在一个问题:当使用的 key 不存在的时候会报 KeyError,而 defaultdict 就比较厉害了,我们完全不需要检查 key 是否存在,所以我们能像下面这样做的随心所欲:

from collections import defaultdict

languages = (
  ('rocky', 'python'),
  ('snow', 'c'),
  ('leey', 'java'),
  ('rocky', 'c++'),
  ('leey', 'c#')
)

favourite = defaultdict(list)

for name, language in languages:
  favourite[name].append(language)

print(favourite)

输出如下所示:

defaultdict(<type 'list'>, {'leey': ['java', 'c#'], 'rocky': ['python', 'c++'], 'snow': ['c']})

然后我们再回到“键不存在,会触发 KeyError 异常”这个问题上来,我们先来看 dict 触发 KeyError 的例子:

my_dict = {}
my_dict['name']['like'] = 'python'

输出如下:

KeyError: 'name'

defaultdict 则用了一个非常巧妙的方式绕过了这个问题,请看下面的操作:

import collections
language = lambda : collections.defaultdict(language)
my_dict = language()
my_dict['name']['like'] = 'python'

运行一下显示正常,我们可以用 json.dumps 打印出 my_dict 的内容:

import json
print(json.dumps(my_dict))

运行结果如下:

{"name": {"like": "python"}}

Counter

Counter 是一个计数器,它可以帮助我们针对某项数据进行计数,比如可以用它来统计每个人擅长的编程语言:

from collections import Counter

languages = (
('rocky', 'python'),
('snow', 'c'),
('leey', 'java'),
('rocky', 'c++'),
('leey', 'c#')
)

cnt = Counter(name for name, language in languages)
print(cnt)

运行结果如下所示:

Counter({'leey': 2, 'rocky': 2, 'snow': 1})

当然我们也可以用它来统计一个文件,比如:

from collections import Counter

with open('test.txt', 'rb') as f:
line_cnt = Counter(f)

print(line_cnt)

deque

deque 提供了一个双端队列,我们可以在首尾两端添加或者删除元素

想要使用 deque,首先我们要从 collections 中导入 deque 模块,然后创建一个 deque 对象,它的用法就像我们前面学过的 list 一样,并且提供了类似的方法,具体如下所示:

from collections import deque

deq = deque()
deq.append(1)
deq.append(2)
deq.append(3)
print(deq)
print(len(deq))
print(deq[0])
print(deq[-1])

输出结果如下:

deque([1, 2, 3])
3
1
3

我们可以从两端取出数据:

from collections import deque

deq = deque(range(5))
print('len(deq) == {}'.format(len(deq)))
deq.popleft()
deq.pop()
print(deq)

输出的结果如下所示:

len(deq) == 5
deq == deque([1, 2, 3])

我们也可以对这个列表的大小进行限制,当超出我们的限制的时候,数据会从另一端被 pop 出去,具体我们来看下面的操作:

from collections import deque

deq = deque(maxlen=3)
deq.append(1)
deq.append(2)
deq.append(3)
print(deq)
deq.append(4)
print (deq)

输出的结果如下:

deque([1, 2, 3], maxlen=3)
deque([2, 3, 4], maxlen=3)

当超出 maxlen 的值时,最左边的数据将从队列中删除。

当然我们还可以从任意一端扩展这个双端队列中的数据:

from collections import deque

deq = deque([1,2,3])
deq.extendleft([0])
deq.extend([4,5,6])
print(deq)

输出的结果如下所示:

deque([0, 1, 2, 3, 4, 5, 6])

以上就是详解Python 中的容器 collections的详细内容,更多关于python collections的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
python 从远程服务器下载日志文件的程序
Feb 10 Python
python翻译软件实现代码(使用google api完成)
Nov 26 Python
python脚本设置超时机制系统时间的方法
Feb 21 Python
Python的Flask站点中集成xhEditor文本编辑器的教程
Jun 13 Python
Django中使用celery完成异步任务的示例代码
Jan 23 Python
Python 数据处理库 pandas进阶教程
Apr 21 Python
Python使用matplotlib绘制三维参数曲线操作示例
Sep 10 Python
Pytorch 多维数组运算过程的索引处理方式
Dec 27 Python
python将logging模块封装成单独模块并实现动态切换Level方式
May 12 Python
Python使用plt.boxplot() 参数绘制箱线图
Jun 04 Python
基于PyTorch的permute和reshape/view的区别介绍
Jun 18 Python
序列化Python对象的方法
Aug 01 Python
Python 解析库json及jsonpath pickle的实现
Aug 17 #Python
Python实现爬取网页中动态加载的数据
Aug 17 #Python
Python 如何操作 SQLite 数据库
Aug 17 #Python
Python使用正则表达式实现爬虫数据抽取
Aug 17 #Python
Python 通过正则表达式快速获取电影的下载地址
Aug 17 #Python
Python 程序员必须掌握的日志记录
Aug 17 #Python
Python使用urlretrieve实现直接远程下载图片的示例代码
Aug 17 #Python
You might like
PHP 数组入门教程小结
2009/05/20 PHP
php抽象类用法实例分析
2015/07/07 PHP
Laravel5.1 框架响应基本用法实例分析
2020/01/04 PHP
javascript 表单的友好用户体现
2009/01/07 Javascript
js实现权限树的更新权限时的全选全消功能
2009/02/17 Javascript
基于mouseout和mouseover等类似事件的冒泡问题解决方法
2013/11/18 Javascript
JQuery性能优化的几点建议
2014/05/14 Javascript
JQuery中绑定事件(bind())和移除事件(unbind())
2015/02/27 Javascript
jquery利用命名空间移除绑定事件的方法
2015/03/11 Javascript
JavaScript处理解析JSON数据过程详解
2015/09/11 Javascript
BootStrap创建响应式导航条实例代码
2016/05/31 Javascript
JavaScript获取短信验证码(周期性)
2016/12/29 Javascript
Jquery实现跨域异步上传文件总结
2017/02/03 Javascript
使用vue实现grid-layout功能实例代码
2018/01/05 Javascript
详解ES6 CLASS在微信小程序中的应用实例
2020/04/24 Javascript
vue 解决uglifyjs-webpack-plugin打包出现报错的问题
2020/08/04 Javascript
[01:50:49]DOTA2-DPC中国联赛 正赛 PSG.LGD vs Aster BO3 第三场 1月24日
2021/03/11 DOTA
python 安装virtualenv和virtualenvwrapper的方法
2017/01/13 Python
使用Django启动命令行及执行脚本的方法
2018/05/29 Python
python实现批量图片格式转换
2020/06/16 Python
Python玩转加密的技巧【推荐】
2019/05/13 Python
Python 正则表达式 re.match/re.search/re.sub的使用解析
2019/07/22 Python
python实现桌面气泡提示功能
2019/07/29 Python
Python计算IV值的示例讲解
2020/02/28 Python
一篇文章带你搞定Ubuntu中打开Pycharm总是卡顿崩溃
2020/11/02 Python
使用HTML5 Geolocation实现一个距离追踪器
2018/04/09 HTML / CSS
海外淘书首选:AbeBooks
2017/07/31 全球购物
联想德国官网:Lenovo Germany
2018/07/04 全球购物
3个CCIE对一个工程师的面试题
2012/05/06 面试题
超市中秋节活动方案
2014/02/12 职场文书
五水共治一句话承诺
2014/05/30 职场文书
教师创先争优承诺书
2015/04/27 职场文书
创业计划书之废品回收
2019/09/26 职场文书
职场:企业印章管理制度(模板)
2019/10/18 职场文书
Python实现拼音转换
2021/06/07 Python
解析探秘fescar分布式事务实现原理
2022/02/28 Java/Android