本文最初发表在DigitalOcean的公共知识库中。我在这里对它进行了一些较小的编辑。
介绍
Python 3有许多内置的数据结构,包括元组、字典和列表。数据结构为我们提供了一种组织和存储数据的方法。collections模块能够帮助我们高效地填充和操作数据结构。
在本教程中,我们将通过collections模块中的三个类来帮助你处理元组、字典和列表。我们将使用namedtuples来创建带有命名字段的元组,使用defaultdict来在字典中精确地分组信息,以及使用deque来高效地向一个类列表对象的每一边添加元素。
在本教程中,我们将主要处理一个鱼类清单,当在虚构的水族箱中添加或删除鱼类时,我们需要修改这些清单。
必备条件
要充分理解本教程,建议你熟悉元组、字典和列表数据类型(包括它们的语法),以及如何从它们中检索数据。你可以查看这些教程,以获得必要的背景信息:
理解Python 3中的元组
理解python3中的字典
Python 3中的理解列表
向元组添加命名字段
Python元组是一个不可变的,或不可改变的,有序的元素序列。元组经常用来表示纵列数据;例如,一个CSV文件中的行数或一个SQL数据库中的行数。一个水族箱可以用一系列元组来记录它的鱼类的库存。
一个单独的鱼类元组:
这个元组由三个字符串元素组成。
虽然在某些方面很有用,但是这个元组并没有清楚地指明它的每个字段代表什么。实际上,元素0是一个名称,元素1是一个物种,元素2是一个饲养箱。
鱼类元组字段说明:
这个表清楚地表明,该元组的三个元素都有明确的含义。
来自collections模块的namedtuple允许你向一个元组的每个元素添加显式名称,以便在你的Python程序中明确这些元素的含义。
让我们使用namedtuple来生成一个类,从而明确地命名鱼类元组的每个元素:
from collections import namedtuple 可以让你的Python程序访问namedtuple工厂函数。namedtuple函数调用会返回一个绑定到名称Fish的类。namedtuple函数有两个参数:我们的新类“Fish”的期望名称和命名元素["name"、"species”、“tank"]的一个列表。
我们可以使用Fish类来表示前面的鱼类元组:
如果我们运行这段代码,我们将看到以下输出:
sammy是使用Fish类进行实例化的。sammy是一个具有三个明确命名元素的元组。
sammy的字段可以通过它们的名称或者一个传统的元组索引来访问:
如果我们运行这两个print调用,我们将看到以下输出:
访问.species会返回与使用[1]访问sammy的第二个元素相同的值。
使用collections模块中的namedtuple可以在维护元组(即它们是不可变的、有序的)的重要属性的同时使你的程序更具可读性。
此外,namedtuple工厂函数还会向Fish实例添加几个额外的方法。
使用._asdict将一个实例转换为字典:
如果我们运行print,你会看到如下输出:
在sammy上调用.asdict将返回一个字典,该字典会将三个字段名称分别映射到它们对应的值。
大于3.8的Python版本输出这一行的方式可能略有不同。例如,你可能会看到一个OrderedDict,而不是这里显示的普通字典。
备注: 在Python中,带有前导下划线的方法通常被认为是“私有的”。但是,namedtuple提供的其他方法(如._asdict、._make、._replace等)是公开的。
在字典中收集数据
在Python字典中收集数据通常是很有用的。collections模块中的defaultdict可以帮助我们快速、简洁地将信息集合到字典中。
defaultdict绝不会引发一个KeyError。如果一个键不存在,defaultdict会插入并返回一个占位符值来代替:
如果我们运行这段代码,我们将看到如下输出:
defaultdict会插入并返回一个占位符值,而不是引发一个KeyError。在本例中,我们将占位符值指定为一个列表。
相比之下,常规字典会在缺失的键上引发一个KeyError:
如果我们运行这段代码,我们将看到如下输出:
当我们试图访问一个不存在的键时,常规字典my_regular_dict会引发一个KeyError。
defaultdict的行为与常规字典不同。defaultdict会不带任何参数调用占位符值来创建一个新对象,而不是在缺失的键上引发一个KeyError。在本例中,是调用list创建一个空列表。
继续我们虚构的水族箱示例,假设我们有一个表示水族箱清单的鱼类元组列表:
水族箱中有三种鱼——它们的名字、种类和饲养箱在这三个元组中都有指出。
我们的目标是按饲养箱组织我们的清单—我们想知道每个饲养箱中存在的鱼的列表。换句话说,我们需要一个能将“tank-a”映射到["Jamie