
集合是 Python 中无序、可变、元素唯一 的数据结构,基于哈希表实现,适用于去重和集合运算(交集、并集、差集等)。
一、集合的创建
1. 基本创建方式
# 使用花括号
s1 = {1, 2, 3}
print(type(s1)) # <class 'set'>
# 使用 set() 构造函数
s2 = set([1, 2, 3]) # 从列表创建
s3 = set("hello") # 从字符串创建
print(s3) # {'h', 'e', 'l', 'o'}(自动去重,无序)
# 空集合(注意:{} 是空字典)
empty_set = set() # 正确
empty_dict = {} # 这是字典
# 集合推导式
squares = {x**2 for x in range(5)}
print(squares) # {0, 1, 4, 9, 16}
二、集合的特性
1. 元素唯一性(自动去重)
# 重复元素会被自动去重
numbers = {1, 2, 2, 3, 3, 3, 4}
print(numbers) # {1, 2, 3, 4}
# 去重应用
names = ["Alice", "Bob", "Alice", "Charlie", "Bob"]
unique_names = set(names)
print(unique_names) # {'Bob', 'Charlie', 'Alice'}
2. 无序性
# 集合不保证顺序
s = {3, 1, 2}
print(s) # {1, 2, 3}(实际输出顺序可能不同,取决于哈希)
3. 元素必须是可哈希的(不可变类型)
# 可哈希类型
s1 = {1, 2, 3} # 整数
s2 = {"a", "b", "c"} # 字符串
s3 = {(1, 2), (3, 4)} # 元组
# ❌ 不可哈希类型
# s4 = {[1, 2], [3, 4]} # TypeError: list is unhashable
# s5 = {{1, 2}, {3, 4}} # TypeError: set is unhashable
三、集合的常用操作
1. 添加元素
s = {1, 2, 3}
# add():添加单个元素
s.add(4)
print(s) # {1, 2, 3, 4}
s.add(2) # 已存在,无变化
# update():添加多个元素(可迭代对象)
s.update([5, 6, 7])
print(s) # {1, 2, 3, 4, 5, 6, 7}
s.update("abc") # 添加字符串的每个字符
print(s) # {1, 2, 3, 4, 5, 6, 7, 'a', 'b', 'c'}
2. 删除元素
s = {1, 2, 3, 4, 5}
# remove():删除指定元素(不存在会报错 KeyError)
s.remove(3)
print(s) # {1, 2, 4, 5}
# s.remove(10) # KeyError
# discard():删除指定元素(不存在不会报错)
s.discard(10) # 什么都不发生
s.discard(5) # 删除 5
# pop():随机删除并返回一个元素(集合无序)
removed = s.pop()
print(f"删除了: {removed}")
# clear():清空集合
s.clear()
print(s) # set()
3. 成员检查
s = {1, 2, 3, 4, 5}
print(3 in s) # True
print(10 in s) # False
print(3 not in s) # False
四、集合运算
1. 交集(&)
A = {1, 2, 3, 4}
B = {3, 4, 5, 6}
# 方法1:使用运算符
print(A & B) # {3, 4}
# 方法2:使用 intersection()
print(A.intersection(B)) # {3, 4}
# 原地修改
A.intersection_update(B) # A 变为 {3, 4}
2. 并集(|)
A = {1, 2, 3}
B = {3, 4, 5}
print(A | B) # {1, 2, 3, 4, 5}
print(A.union(B)) # {1, 2, 3, 4, 5}
# 原地修改
A.update(B) # A 变为 {1, 2, 3, 4, 5}
3. 差集(-)
A = {1, 2, 3, 4}
B = {3, 4, 5, 6}
print(A - B) # {1, 2}(在 A 但不在 B)
print(B - A) # {5, 6}(在 B 但不在 A)
print(A.difference(B)) # {1, 2}
# 原地修改
A.difference_update(B) # A 变为 {1, 2}
4. 对称差集(^)
A = {1, 2, 3, 4}
B = {3, 4, 5, 6}
print(A ^ B) # {1, 2, 5, 6}(不同时在 A 和 B 中的元素)
print(A.symmetric_difference(B)) # {1, 2, 5, 6}
五、集合的比较
1. 子集(<=)和真子集(<)
A = {1, 2}
B = {1, 2, 3, 4}
C = {1, 2}
print(A <= B) # True(A 是 B 的子集)
print(A <= C) # True(A 是 C 的子集)
print(A < B) # True(A 是 B 的真子集)
print(A < C) # False(A 不是 C 的真子集,相等)
print(A.issubset(B)) # True
2. 超集(>=)和真超集(>)
B = {1, 2, 3, 4}
A = {1, 2}
print(B >= A) # True(B 是 A 的超集)
print(B > A) # True(B 是 A 的真超集)
print(B.issuperset(A)) # True
3. 不相交
A = {1, 2, 3}
B = {4, 5, 6}
C = {3, 4, 5}
print(A.isdisjoint(B)) # True(没有共同元素)
print(A.isdisjoint(C)) # False(有共同元素 3)
六、集合的遍历
fruits = {"苹果", "香蕉", "橘子", "葡萄"}
# 遍历元素
for fruit in fruits:
print(fruit)
# 带索引遍历(需要转换为列表)
for i, fruit in enumerate(fruits):
print(f"{i}: {fruit}")
# 排序后遍历
for fruit in sorted(fruits):
print(fruit)
七、frozenset(不可变集合)
frozenset 是集合的不可变版本,可以作为字典的键或集合的元素。
# 创建 frozenset
fs = frozenset([1, 2, 3])
print(type(fs)) # <class 'frozenset'>
# 不可变特性
# fs.add(4) # AttributeError
# fs.remove(1) # AttributeError
# 可以作为字典的键
d = {frozenset([1, 2]): "value"}
# 可以作为集合的元素
s = {frozenset([1, 2]), frozenset([3, 4])}
# 支持集合运算(返回新 frozenset)
fs1 = frozenset([1, 2, 3])
fs2 = frozenset([2, 3, 4])
print(fs1 & fs2) # frozenset({2, 3})
print(fs1 | fs2) # frozenset({1, 2, 3, 4})
汇总表
| 操作 | 方法 | 运算符 | 说明 |
|---|---|---|---|
| 添加元素 | add() |
- | 添加单个元素 |
| 添加多个 | update() |
- | 添加多个元素 |
| 删除元素 | remove() |
- | 不存在报错 |
| 安全删除 | discard() |
- | 不存在不报错 |
| 随机删除 | pop() |
- | 删除并返回随机元素 |
| 交集 | intersection() |
& |
共同元素 |
| 并集 | union() |
` | ` |
| 差集 | difference() |
- |
在 A 不在 B |
| 对称差集 | symmetric_difference() |
^ |
不同时在 A 和 B |
| 子集 | issubset() |
<= |
判断子集 |
| 超集 | issuperset() |
>= |
判断超集 |
| 不相交 | isdisjoint() |
- | 无共同元素 |
说明:
-
集合元素唯一、无序、可变
-
元素必须是可哈希的(不可变类型)
-
成员检查 O(1),比列表快得多
-
适用于去重 和集合运算
-
frozenset是不可变版本,可作字典键 -
使用
{}创建集合时注意与字典区分