返回介绍

集合

发布于 2024-01-29 22:24:17 字数 4838 浏览 0 评论 0 收藏 0

Python 2.4引入了一种新的类型——集合(set),这是一些唯一的、不可变的对象的一个无序集合(collection),这些对象支持与数学集合理论相对应的操作。根据定义,一个项在集合中只能出现一次,不管将它添加了多少次。同样,集合有着广泛的应用,尤其是在涉及数字和数据库的工作中。

因为它是其他对象的集合,因此,它具有列表和字典这样的对象的某些共同行为,而这些对象超出了本章讨论的范围。例如,集合是可以迭代的,可以根据需要增长或缩短,并且能够包含各种对象类型。我们将会看到,一个集合的行为很像一个无值的字典的键,但是,它还支持额外的操作。

然而,由于集合是无序的,并且不会把键匹配到值,它们既不是序列也不是映射类型;它们是自成一体的类型。此外,由于集合本质上具有基本的数学特性(它对于很多读者来说,可能更加学院派,并且比像字典这样更为普遍的对象用得要少很多),在这里,我们将介绍Python的集合对象的基本工具。

Python 2.6中的集合基础知识

根据你使用的是Python 2.6还是Python 3.0,有几种不同方法来创建集合。既然本书涉及这两个版本,让我们先从Python 2.6的情况开始,其方法在Python 3.0中也是可用的(并且有时候还是必须的);稍后,我们将根据Python 3.0的扩展来细化。要创建一个集合对象,向内置的set函数传递一个序列或其他的可迭代的对象:

得到了一个集合对象,其中包含传递的对象的所有元素(注意集合并不包含位置顺序,序列却包含):

集合通过表达式操作符支持一般的数学集合运算。注意,不能在一般序列上应用这些表达式,必须通过序列创建集合后才能使用这些工具。

除了表达式,集合对象还提供了对应这些操作的方法,以及更多的支持改变集合的方法,集合add方法插入一个项目、update是按位置求并集,remove根据值删除一个项目(在任何集合实例或集合类型名上运行dir来查看所有可用的方法)。假设x和y仍然像前面交互中的一样:

作为可迭代的容器,集合也可以用于len、for循环和列表解析这样的操作中。然而,由于它们都是无序的,所以不支持像索引和分片这样的操作:

最后,尽管前面介绍的集合表达式通常需要两个集合,它们基于方法的对应形式往往对任何可迭代类型也有效:

要了解关于集合操作的更多细节,参阅Python的库参考手册,或者其他参考书。尽管集合操作可以在Python中和其他类型(如列表和字典)一起手动编写,Python的内置集合还是使用高效率的算法和实现技术来提供快速和标准的操作。

Python 3.0中的集合常量

如果你认为集合很“酷”,它们最近会变得更酷。在Python 3.0中,我们仍然使用集合内置函数来创建集合对象,但是Python 3.0也添加了新的集合常量形式,该形式使用前面为字典所保留的花括号。在Python 3.0中,如下的形式是等同的:

这个语法是有意义的,因为集合基本上就像是无值的字典,集合的项是无序的、唯一的、不可改变的,因此,它们的行为和字典的键很像。由于字典键列表在Python 3.0中是视图对象,它支持像交集和并集这样的类似集合的行为,这种相似性甚至更加惊人(参见第8章了解关于字典视图对象的更多内容)。

实际上,不管如何创建集合,Python 3.0都使用新的常量格式来显示它。在Python 3.0中要创建空的集合或从已有的可迭代对象构建集合(使用集合解析的简述,将在本章稍后介绍),还是需要内置的set函数,但是新的常量便于初始化具有已知结构的集合:

前面小节中所讨论的所有集合处理操作在Python 3.0中都同样有效,但是结果集合显示有所不同:

注意,在Python中{}仍然是一个字典。空的集合必须通过内置函数set来创建,并且以同样方式显示:

与Python 2.6一样,Python 3.0中用常量创建的集合支持同样的方法,其中的一些支持表达式所不支持的通用可迭代操作数:

不可变限制和冻结集合

集合是强大而灵活的对象,但是,它们在Python 3.0和Python 2.6中都有一个限制,我们需要铭记,很大程度上是由于其实现,集合只能包含不可变的(即可散列的)对象类型。因此,列表和字典不能嵌入到集合中,但是,如果你需要存储复合值的话,元组是可以嵌入的。在集合操作中使用元组的时候,元组比较其完整的值:

例如,集合中的元组可以用来表示日期、记录、IP地址等(本书的本部分后续将更详细地介绍元组)。集合本身也是不可改变的,因此,不能直接嵌入到其他集合中;如果需要在另一个集合中存储一个集合,可以像调用set一样来调用frozenset,但是,它创建一个不可变的集合,该集合不可修改并且可以嵌套到其他集合中。

Python 3.0中的集合解析

除了常量,Python 3.0还引入了一个集合解析构造,它类似于我们在第4章中介绍过的列表解析的形式,但是,编写在花括号中而不是方括号中,并且作用于集合而不是列表。集合解析运行一个循环并在每次迭代时收集一个表达式的结果,通过一个循环变量来访问当前的迭代值以用于集合表达式中。结果是通过运行代码创建的一个新的集合,它具备所有一般的集合行为:

在这个表达式中,循环部分编写在右边,而集合表达式编写在左边(x**2)。和列表解析一样,我们可以很好地理解这个表达式的含义:“对于列表中的每一个X,给出包含X的平方的一个新的集合”。解析也可以迭代其他类型的对象,例如字符串(下面的第一个例子展示了如何从一个已有的可迭代对象创建一个集合):

因为其他的关于解析的知识要依赖于我们现在还不准备介绍的底层概念,这些概念将推迟到本书后面再详细介绍。在第8章中,我们将遇到Python 3.0中的另一种解析,即字典解析,并且,我们随后将介绍关于所有解析(列表、集合、字典和生成器)的更多内容,特别是在第14章和第20章中。随后你将会了解到,在没有学习较大的语句之前,很难理解所有的解析,包括集合、这里所没有介绍的其他语法的支持、包括嵌套循环和if测试等。

为什么使用集合

集合操作有各种各样常见的用途,其中一些比数学更加实用。例如,由于项在集合中只能存储一次,集合(set)可以用来把重复项从其他集合(collection)中过滤掉。直接把集合(collection)转换为一个集合(set),然后再转换回来即可(因为集合是可迭代的,这里的list调用对其有效):

当你遍历图形或其他的回环结构的时候,集合可以用来记录已经访问过的位置。例如,我们将分别在第24章和第30章学习的传递性模块重载和继承树列表程序示例,必须确保访问过的项不再循环。尽管把访问状态作为键记录到字典中很高效,但集合提供了几乎等同的一种替代方式(并且可能更直观或更晦涩,取决你征求谁的意见)。

最后,在处理较大的数据集合的时候(例如,数据库查询结果),两个集合的交集包含了两个领域中共有的对象,并集包含了两个集合中的所有项目。为了说明,这里给出集合操作的一些实际例子,这些操作应用于一个假定公司的人员名单,使用Python 3.0集合常量(在Python 2.6中使用set):

在Python库手册以及关系数据库理论的一些相关资料中,我们可以找到关于集合操作的更多细节。在本书第8章中介绍Python 3.0中的字典视图对象的时候,我们将再次回顾这里所见到的一些集合操作。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文