详解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 相关文章推荐
Tornado Web服务器多进程启动的2个方法
Aug 04 Python
Python基于回溯法子集树模板解决0-1背包问题实例
Sep 02 Python
python使用pandas实现数据分割实例代码
Jan 25 Python
Python实现查找最小的k个数示例【两种解法】
Jan 08 Python
新手如何发布Python项目开源包过程详解
Jul 11 Python
python列表,字典,元组简单用法示例
Jul 11 Python
Python多叉树的构造及取出节点数据(treelib)的方法
Aug 09 Python
docker django无法访问redis容器的解决方法
Aug 21 Python
pygame实现非图片按钮效果
Oct 29 Python
django 实现后台从富文本提取纯文本
Jul 02 Python
Python性能分析工具py-spy原理用法解析
Jul 27 Python
详解anaconda安装步骤
Nov 23 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
phpfans留言版用到的install.php
2007/01/04 PHP
php继承的一个应用
2011/09/06 PHP
解析PHP中一些可能会被忽略的问题
2013/06/21 PHP
Codeigniter实现智能裁剪图片的方法
2014/06/12 PHP
php实现图片等比例缩放代码
2015/07/23 PHP
密码强度检测效果实现原理与代码
2013/01/04 Javascript
UpdatePanel和Jquery冲突的解决方法
2013/04/01 Javascript
javascript控制Div层透明属性由浅变深由深变浅逐渐显示
2013/11/12 Javascript
js中文逗号转英文实现
2014/02/11 Javascript
JavaScript弹出窗口方法汇总
2014/08/12 Javascript
javascript中的Function.prototye.bind
2015/06/25 Javascript
详细分析JavaScript函数定义
2015/07/16 Javascript
如何使用jQuery技术开发ios风格的页面导航菜单
2015/07/29 Javascript
js根据手机客户端浏览器类型,判断跳转官网/手机网站多个实例代码
2016/04/30 Javascript
深入理解node exports和module.exports区别
2016/06/01 Javascript
BootStrap中关于Select下拉框选择触发事件及扩展
2016/11/22 Javascript
JavaScript正则表达式校验与递归函数实际应用实例解析
2017/08/04 Javascript
解决Mac下安装nmp的淘宝镜像失败问题
2018/05/16 Javascript
vue中eslintrc.js配置最详细介绍
2018/12/21 Javascript
[01:43]3.19DOTA2发布会 三代刀塔人第三代
2014/03/25 DOTA
举例简单讲解Python中的数据存储模块shelve的用法
2016/03/03 Python
python中的字典使用分享
2016/07/31 Python
PyTorch-GPU加速实例
2020/06/23 Python
Python 使用office365邮箱的示例
2020/10/29 Python
html5生成柱状图(条形图)效果的实例代码
2016/03/25 HTML / CSS
自动化专业个人求职信范文
2013/11/29 职场文书
财产保全担保书范文
2014/04/01 职场文书
同居协议书范本
2014/04/23 职场文书
医院院务公开实施方案
2014/05/03 职场文书
有关爱国演讲稿
2014/05/07 职场文书
信用社主任竞聘演讲稿
2014/05/23 职场文书
创先争优标语
2014/06/27 职场文书
2015年外联部工作总结
2015/04/03 职场文书
办公用品质量保证书
2015/05/11 职场文书
公司联欢会主持词
2015/07/04 职场文书
2016年中学端午节主题活动总结
2016/04/01 职场文书