问题的历史:
集合(set)作为独立的内置类型从 Python 2.4 开始被引入(在此之前它们作为外部模块实现)。它们允许有效地存储唯一的、无序的元素,并支持许多集合论的标准操作:并集、交集、差集、对称差及子集检查。
问题:
在没有 set 的情况下,必须使用列表,这导致查找唯一元素效率低下,从而使得使用大量包含检查的算法变慢。set 通过哈希表实现,因此所有的查找、添加和删除操作都在摊销 O(1) 时间内完成。然而,这种结构可能会引发意想不到的问题——例如,元素的顺序丢失、元素类型的限制(必须是不可变和可哈希的),以及对集合比较及其与其他结构交互特性的误解。
解决方案:
当需要仅存储唯一元素并对其进行集合论操作时,使用 set。需要记住,元素必须是可哈希的(例如,数字、字符串、元组,但不能是列表或字典)。对于 set,提供了一整套丰富的内置方法(add、remove、union、intersection、difference、issubset 等)。
代码示例:
s1 = {1, 2, 3, 4} s2 = {3, 4, 5} print(s1 | s2) # {1, 2, 3, 4, 5} (并集) print(s1 & s2) # {3, 4} (交集) print(s1 - s2) # {1, 2} (差集) print(3 in s1) # True (包含检查)
关键特点:
可以将可变类型(例如,列表)添加到 set 吗?
不可以,集合的元素必须是可哈希的且不可变的。列表或字典不能添加到集合中,Python 会引发 TypeError。
s = set() s.add([1, 2, 3]) # TypeError: unhashable type: 'list'
set 是否保留元素的顺序?
不保留。从创建集合时开始,元素不保证按添加顺序返回,特别是当集合大小发生变化时。
s = {5, 2, 8, 1} print(s) # 顺序未定义
set 和 frozenset 的区别是什么,是否可以将 frozenset 作为 set 的元素?
frozenset 是 set 的不可变版本。它可以作为另一个 set 的元素或作为字典的键使用,因为它是可哈希的。
fs = frozenset([1, 2, 3]) s = set() s.add(fs) # OK
开发者想要存储唯一元素,选择了 set,但没有考虑到其出现顺序。因此,依赖处理顺序的部分业务逻辑停止工作。
优点:
缺点:
在处理从大集合中快速过滤唯一记录的任务时,选择了 set,因为只需关注唯一性,而不是顺序。性能显著提高,代码更加简洁。
优点:
缺点: