Menu

Python 集合:唯一元素、并集、交集与差集

什么时候该用 Python 集合:元素唯一、快速的 in 检查,以及让集合威力十足的数学运算(并集、交集、差集)。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

集合是一个装着唯一元素的无序容器

列表和元组在意顺序,集合不在意。列表允许重复元素堆积,集合会悄悄丢掉它们。当你有以下两个明确需求时,集合就是合适的数据结构:

  1. 你只想要唯一的元素,没有例外。
  2. 你想快速检查成员关系。

用花括号来写:

第二个集合中重复的 "red" 和 "green" 直接消失了。这不是错误,而正是集合存在的意义。

创建集合

你实际会用到的两种方式:

最后一点每个人都会踩一次坑:{} 创建的是空字典,而不是空集合。这个语法上的歧义总得归属其中一方,最后字典赢了。

添加与删除

remove 和 discard 的区别是关键:remove 要求元素必须存在;discard 则不在乎。根据元素不存在时是否应该报错来选择。

快速的成员检查

这正是集合真正大显身手的地方。无论集合有多大,x in some_set 都是常数时间。x in some_list 则必须逐个遍历列表,列表很大时就会变慢。

经验法则:只要你发现自己在循环里写 if x in some_list,而列表又有几十个以上的元素,就先把列表转换成集合。

集合运算

这是集合真正有趣的地方。你可以用与数学集合运算相对应的运算符来组合它们:

每个运算符也有对应的方法形式(.union()、.intersection()、.difference()、.symmetric_difference())。运算符更简洁;方法形式则可以接收任何可迭代对象,而不只是另一个集合。

列表去重

这是集合最常见的用途之一,甚至不涉及“集合逻辑”:

一行代码,重复元素就没了。有一点需要注意:顺序不会被保留。如果你既需要唯一,又需要保持原来的顺序,请改用 dict.fromkeys():

在现代 Python 中,字典会保持插入顺序,而 dict.fromkeys 用可迭代对象中的元素作为键来构建字典,效果上就是一个有序集合。

子集与超集

检查一个集合是否包含在另一个集合中:

这些在权限检查之类的场景中会用到(“这个用户是否拥有所有必需的角色?”)。

什么能放进集合

只有可哈希的元素。这是一个技术术语,实际上意味着:

  • 不可变的东西是可哈希的:数字、字符串、由可哈希元素组成的元组、frozenset。
  • 可变的东西不可哈希:列表、字典和其他集合都不能作为集合的成员。

如果你需要一个由集合组成的集合,请使用 frozenset,它是集合的不可变版本。

遍历是无序的

遍历集合时,元素的顺序没有任何保证:

多运行几次,你会看到顺序发生变化。如果顺序很重要,集合就不是合适的结构:需要时对内容排序,或者使用列表。

什么时候不该用集合

只要以下任何一条成立,列表或字典可能更合适:

  • 你在意顺序。
  • 你需要存储重复元素。
  • 每个元素都有关联的数据(使用字典,把元素作为键)。

继续前进

集合负责处理唯一性和成员关系。接下来要讲的字典,处理的是更通用的“按键查找值”模式,它可能是 Python 中除列表之外最有用的数据结构。

常见问题

Python 集合是什么?

集合是由唯一元素组成的无序集合。集合使用花括号,但里面没有键值对:colors = {'red', 'green', 'blue'}。同一个值添加两次不会有任何效果,重复的元素会被悄悄丢弃。

什么时候应该用集合而不是列表?

当你在意元素唯一,或者要做很多次成员检查(x in collection)时,就用集合。集合会自动去重,并且成员检查是常数时间,对于大型集合来说,比列表快得多。

Python 中如何创建空集合?

使用 set(),而不是 {}:里面什么都没有的花括号创建的是空字典,而不是空集合。有了集合之后,就可以用 .add(value) 添加元素。

Coddy 编程语言插图

和 Coddy 一起学编程

开始