一、什么是集合(Set)?
Python 的集合是一个无序、可变、不重复元素的集合。它基于一种叫做哈希表的数据结构实现,这决定了它的核心特性。
核心特性:
- 无序性(Unordered): 集合中的元素没有固定的顺序。你无法通过索引(如
my_set[0]
)来访问元素,因为每次输出的顺序可能都不一样。 - 元素唯一性(Unique Elements): 集合会自动去除重复的元素。这是它最常用的功能之一。
- 可变性(Mutable): 你可以向集合中添加或移除元素,但集合本身包含的元素必须是不可变类型(Immutable),如数字、字符串、元组等。你不能将列表或字典放入集合中。
- 支持数学集合运算: 如并集、交集、差集等,非常高效。
二、集合的创建
可以使用花括号 {}
或 set()
函数来创建集合。
注意: 创建空集合必须使用 set()
,因为 {}
创建的是一个空字典。
# 1. 使用花括号创建非空集合
fruits = {"apple", "banana", "cherry", "apple"} # 重复的"apple"会被自动去除
print(fruits) # 输出: {'cherry', 'banana', 'apple'} (顺序可能不同)# 2. 使用 set() 函数创建
numbers = set([1, 2, 3, 2, 1]) # 从列表创建
print(numbers) # 输出: {1, 2, 3}chars = set("hello") # 从字符串创建,会拆分成单个字符
print(chars) # 输出: {'h', 'e', 'l', 'o'} (注意只有一个'l')# 3. 创建空集合
empty_set = set()
print(empty_set) # 输出: set()
print(type(empty_set)) # 输出: <class 'set'>not_a_set = {}
print(type(not_a_set)) # 输出: <class 'dict'>
三、集合的基本操作与方法
1. 添加元素
add(element)
: 添加单个元素。update(iterable)
: 添加来自可迭代对象(如列表、元组、其他集合)的多个元素。
my_set = {1, 2, 3}
my_set.add(4)
print(my_set) # {1, 2, 3, 4}my_set.update([3, 4, 5, 6]) # 重复的3,4会被忽略
print(my_set) # {1, 2, 3, 4, 5, 6}
2. 移除元素
remove(element)
: 移除指定元素。如果元素不存在,会引发KeyError
错误。discard(element)
: 移除指定元素。如果元素不存在,不会引发错误,什么也不做。(更安全,推荐使用)pop()
: 随机移除并返回一个元素。因为集合是无序的。clear()
: 清空集合,移除所有元素。
my_set = {1, 2, 3, 4, 5}
my_set.discard(3) # 成功移除
my_set.discard(10) # 元素10不存在,但不会报错my_set.remove(4) # 成功移除
# my_set.remove(10) # 会引发 KeyErrorpopped_item = my_set.pop() # 随机弹出一个,比如 1
print(popped_item, my_set) # 1 {2, 5}my_set.clear()
print(my_set) # set()
3. 成员检测(非常高效!)
使用 in
关键字来检查一个元素是否存在于集合中。由于基于哈希表,这个操作的时间复杂度接近 O(1),速度极快,远快于列表(O(n))。
my_set = {"a", "b", "c"}
print("a" in my_set) # True
print("z" in my_set) # False
4. 遍历集合
使用 for
循环遍历,但顺序是不确定的。
for item in my_set:print(item)
四、集合的数学运算
这是集合类型最强大的功能,可以直观地进行数学上的集合操作。
假设有两个集合:
A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}
| 操作 | 运算符 | 方法 | 描述 | 示例结果 |
| :--- | :--- | :--- | :--- | :--- |
| 并集 | |
| union()
| 返回所有在 A 或 B 中的元素 | A | B
-> {1, 2, 3, 4, 5, 6, 7, 8}
|
| 交集 | &
| intersection()
| 返回所有同时在 A 和 B 中的元素 | A & B
-> {4, 5}
|
| 差集 | -
| difference()
| 返回在 A 中但不在 B 中的元素 | A - B
-> {1, 2, 3}
|
| 对称差集 | ^
| symmetric_difference()
| 返回只在 A 或只在 B 中的元素(排除交集) | A ^ B
-> {1, 2, 3, 6, 7, 8}
|
这些操作符都有对应的“原地更新”方法,会直接修改原集合:
update()
(|=)intersection_update()
(&=)difference_update()
(-=)symmetric_difference_update()
(^=)
A = {1, 2, 3}
B = {3, 4, 5}
A.difference_update(B) # 等同于 A -= B
print(A) # {1, 2},A被永久修改了
5. 集合关系判断
- 子集(Subset):
issubset()
或<=
- 真子集(Proper Subset):
<
- 超集(Superset):
issuperset()
或>=
- 真超集(Proper Superset):
>
- 是否无交集:
isdisjoint()
C = {1, 2}
D = {1, 2, 3}
print(C.issubset(D)) # True
print(C < D) # True (C是D的真子集)
print(D.issuperset(C)) # True
print(A.isdisjoint(B)) # 检查A和B是否没有共同元素
五、集合推导式(Set Comprehension)
类似于列表推导式,可以快速生成集合。
# 创建一个包含前10个数字平方的集合
squares = {x**2 for x in range(10)}
print(squares) # {0, 1, 64, 4, 36, 9, 16, 49, 81, 25} (顺序随机)# 从一个列表中快速去重并转换
words = ["hello", "world", "hello", "python"]
unique_lengths = {len(word) for word in words}
print(unique_lengths) # {5, 6} (hello=5, world=5, python=6)
六、核心使用场景
1. 快速去重(最常用)
这是集合最简单直接的应用。当你有一个包含重复元素的可迭代对象(如列表)时,将其转换为集合是去重的最快方法。
my_list = [1, 2, 2, 3, 4, 4, 4, 5]
unique_list = list(set(my_list)) # 先转集合去重,再转回列表
print(unique_list) # 输出可能是 [1, 2, 3, 4, 5] (顺序可能改变)
注意: 这种方法会丢失原始列表的顺序。如果需要保持顺序,可以使用 dict.fromkeys(my_list)
技巧:
unique_ordered_list = list(dict.fromkeys(my_list))
print(unique_ordered_list) # [1, 2, 3, 4, 5] (顺序保持不变)
2. 高效成员测试
当你需要频繁检查某个元素是否存在于一个大型数据集中时,集合的效率远高于列表。
# 糟糕的做法(对于大型列表)
big_list = [...] # 一个包含一百万个元素的列表
if "target" in big_list: # 需要遍历整个列表,最坏情况O(n)pass# 优秀的做法
big_set = set(big_list) # 花费一次性的时间创建集合
if "target" in big_set: # 后续的每次查询都接近O(1)时间pass
数据库查询、词法分析器、网络爬虫记录已访问的URL等场景都大量使用集合进行成员检测。
3. 进行数学集合运算
任何需要找共同点、差异点的场景都非常适合。
- 找共同好友/兴趣:你的好友列表
friends_me
和另一个人的好友列表friends_her
,共同好友就是friends_me & friends_her
。 - 找出只在A或B中出现过的元素:对比两个版本的软件功能列表,新增功能是
ver2 - ver1
,废弃功能是ver1 - ver2
。 - 分类标签系统:带有“科幻”和“喜剧”标签的电影是
movies_scifi & movies_comedy
。
4. 过滤和筛选数据
结合集合的高效查询,可以快速筛选出符合条件的数据。
# 有一个所有商品的列表 `all_products`
# 有一个用户已购买商品的列表 `purchased_products`
# 快速找出用户未购买的商品
available_products = set(all_products) - set(purchased_products)
七、集合 vs 列表 vs 元组 vs 字典
| 特性 | 列表(List) | 元组(Tuple) | 字典(Dict) | 集合(Set) |
| :--- | :--- | :--- | :--- | :--- |
| 语法 | [1, 2, 3]
| (1, 2, 3)
| {'a': 1}
| {1, 2, 3}
|
| 有序 | 是 | 是 | 是(Py3.7+) | 否 |
| 可变 | 是 | 否 | 是 | 是 |
| 元素要求 | 任何对象 | 任何对象 | 键:不可变;值:任何 | 不可变 |
| 元素唯一 | 否 | 否 | 键唯一 | 是 |
| 主要用途 | 存储有序序列 | 存储不可变序列 | 键值对映射 | 去重、集合运算、成员测试 |
总结
Python 的集合是一个被低估但极其强大的数据结构。它的核心优势在于:
- 基于哈希实现,带来了 O(1) 级别的成员检测效率。
- 自动去重的特性,让数据清理变得异常简单。
- 内置的数学集合运算,让逻辑表达清晰且高效。
当你遇到去重、判断是否存在、找共同/不同项这类问题时,首先就应该考虑使用集合。