Python3 集合 超详细新手教程(全示例 + 逐点讲解 + 避坑指南)
集合(set)是 Python 中专门用来自动去重、做集合数学运算的容器,你可以把它理解成一个 “没有重复元素、没有顺序的货架”。它最核心的两个作用是:快速去重、快速计算交集 / 并集 / 差集,是处理数据去重、多组数据对比时非常高效的工具。
本文从零讲起,所有代码均可直接复制运行验证。
一、什么是集合?核心特点
1. 基础定义
集合用英文大括号 {} 包裹,内部多个元素用英文逗号分隔,和字典不同:字典是 键:值 成对出现,集合只有单个元素。
# 定义一个集合s = {"苹果", "香蕉", "橙子", "苹果"}print(s)print(type(s)) # 查看类型:<class 'set'>
运行结果:
你会发现,重复的 “苹果” 自动消失了 —— 这就是集合的自动去重特性。
2. 核心特点(新手必记,和列表 / 字典对比)
简单总结:存一堆数据、需要去重、需要做 “共同元素 / 独有元素” 对比时,用集合最方便。
二、集合的 3 种定义方式
1. 直接大括号定义(非空集合)
最常用的写法,元素之间用逗号分隔:
# 存储不重复的水果fruits = {"苹果", "香蕉", "橙子", "西瓜"}# 存储数字(自动去重)nums = {1, 2, 3, 2, 1, 4}print(nums) # {1, 2, 3, 4} 重复元素自动去掉
2. ⚠️ 空集合定义(新手头号大坑)
绝对不能用 {} 定义空集合!{} 默认是空字典。 空集合必须用 set() 函数定义:
# ❌ 错误:这是空字典,不是空集合s1 = {}print(type(s1)) # <class 'dict'># ✅ 正确:空集合s2 = set()print(s2) # set()print(type(s2)) # <class 'set'>
3. set () 转换定义(最常用,去重神器)
把列表、元组、字符串等序列转成集合,自动去重,这是日常开发最常用的场景。
# 列表转集合:自动去重lst = [1, 2, 3, 2, 1, 4, 5]s = set(lst)print(s) # {1, 2, 3, 4, 5}# 字符串转集合:每个字符是一个元素,自动去重s2 = set("hello world")print(s2) # {'h', 'e', 'l', 'o', ' ', 'w', 'r', 'd'}# 元组转集合t = (10, 20, 10, 30)s3 = set(t)print(s3) # {10, 20, 30}
💡 实用技巧:列表去重一行搞定
lst = [5, 2, 3, 2, 5, 1]# 列表→集合(去重)→转回列表new_lst = list(set(lst))print(new_lst) # [1, 2, 3, 5] 去重完成
注意:转成集合后顺序会丢失,需要排序可以再加 sorted()。
三、集合的核心特性深入理解
1. 自动去重(最核心价值)
集合不允许重复元素,存入重复元素会自动忽略,不会报错。
s = {"a", "b", "a", "c", "b"}print(s) # {'a', 'b', 'c'} 重复的都被去掉了print(len(s)) # 3 实际只有3个元素
2. 无序性:不能通过索引取值
集合没有顺序,所以不能用下标 / 索引取元素,也没有切片操作,尝试索引会直接报错:
s = {10, 20, 30}# ❌ 错误:集合不支持索引# print(s[0]) # TypeError: 'set' object is not subscriptable
如果需要按顺序取值,先转成列表 / 元组再操作。
3. 元素必须是不可变类型
集合的元素必须是 “不可变类型”(数字、字符串、元组、布尔值),列表、字典、集合本身不能当集合元素,否则会报错。
# ✅ 正确:元素是不可变类型s = {10, "hello", (1,2,3), True}# ❌ 错误:列表是可变类型,不能当集合元素# s = {[1,2], 3} # TypeError: unhashable type: 'list'
四、集合的增删改查操作
集合是可变容器,可以动态添加、删除元素,但因为无序,所以没有 “修改指定位置元素” 的说法。
4.1 增:添加元素
① add () 添加单个元素
s = {"苹果", "香蕉"}s.add("橙子")print(s) # {'苹果', '香蕉', '橙子'}# 添加重复元素:自动忽略,不会报错s.add("苹果")print(s) # 还是 {'苹果', '香蕉', '橙子'}
② update () 批量添加元素
把列表、元组、字符串里的元素拆出来,逐个加入集合:
s = {1, 2, 3}# 批量添加列表里的元素s.update([4, 5, 6])print(s) # {1, 2, 3, 4, 5, 6}# 也可以同时传多个序列s.update([7,8], (9,10))print(s) # {1,2,3,4,5,6,7,8,9,10}
⚠️ 新手区分:add vs update
- update:把参数拆成多个元素逐个加进去 和列表的 append /extend 逻辑非常像。
4.2 删:删除元素
| | |
|---|
remove(元素) | | |
discard(元素) | | |
pop() | | |
clear() | | |
① remove () 删除指定元素
s = {"苹果", "香蕉", "橙子"}s.remove("香蕉")print(s) # {'苹果', '橙子'}# 删除不存在的元素:直接报错# s.remove("西瓜") # KeyError: '西瓜'
② discard () 安全删除(推荐日常用)
元素存在就删除,不存在就什么也不做,不会报错:
s = {"苹果", "香蕉", "橙子"}s.discard("香蕉")print(s) # {'苹果', '橙子'}# 删除不存在的元素:静默忽略,不报错s.discard("西瓜")print(s) # 正常运行
③ pop () 随机删除
因为集合无序,所以是随机删除一个元素,返回被删掉的值:
s = {10, 20, 30, 40}item = s.pop()print("被删除的元素:", item)print("剩余集合:", s)
④ clear () 清空集合
s = {1, 2, 3}s.clear()print(s) # set() 空集合
4.3 查:判断元素是否存在
集合不能用索引取值,只能判断元素是否存在,用 in / not in,查找速度非常快(数据越多优势越明显)。
s = {"苹果", "香蕉", "橙子"}print("香蕉" in s) # Trueprint("西瓜" in s) # Falseprint("西瓜" not in s)# True
4.4 统计长度 len ()
s = {1, 2, 3, 4}print(len(s)) # 4
五、集合的数学运算(核心特色,独有的功能)
这是集合最强大、最有辨识度的功能,对应数学里的集合运算:交集、并集、差集、对称差集,处理两组数据的对比时非常高效。
假设有两个集合:
A = {1, 2, 3, 4, 5}B = {4, 5, 6, 7, 8}
1. 交集:两个集合都有的元素
# 两种写法效果一样print(A & B) # {4, 5}print(A.intersection(B)) # {4, 5}
场景:找两个班级都参加了兴趣班的同学、找两个列表都有的元素。
2. 并集:两个集合所有元素合起来(自动去重)
print(A | B) # {1,2,3,4,5,6,7,8}print(A.union(B)) # {1,2,3,4,5,6,7,8}
场景:合并两组数据,去掉重复项。
3. 差集:A 有但 B 没有的元素
注意:顺序不一样,结果完全不同。
# A有、B没有的元素print(A - B) # {1, 2, 3}print(A.difference(B)) # {1, 2, 3}# B有、A没有的元素print(B - A) # {8, 6, 7}print(B.difference(A)) # {8, 6, 7}
场景:找只在 A 组出现、不在 B 组出现的数据。
4. 对称差集:只在其中一个集合出现的元素(去掉共同部分)
通俗说就是 “两个集合各自独有的元素合起来”,等于并集减去交集。
- 方法:
symmetric_difference()
print(A ^ B) # {1, 2, 3, 6, 7, 8}print(A.symmetric_difference(B)) # {1, 2, 3, 6, 7, 8}
六、集合的其他常用操作
1. 判断子集 / 超集
- 子集:A 的所有元素都在 B 里,A 就是 B 的子集
- 超集:B 包含 A 的所有元素,B 就是 A 的超集
A = {1, 2, 3}B = {1, 2, 3, 4, 5}# 判断A是不是B的子集print(A.issubset(B)) # Trueprint(A <= B) # 符号写法,同上# 判断B是不是A的超集print(B.issuperset(A)) # Trueprint(B >= A) # 符号写法,同上
2. 判断两个集合是否没有交集
A = {1, 2, 3}B = {4, 5, 6}# 两个集合没有共同元素,返回Trueprint(A.isdisjoint(B)) # True
七、集合的典型实用场景
场景 1:列表快速去重
# 原始列表有大量重复user_ids = [101, 102, 103, 101, 102, 105]# 一行去重unique_ids = list(set(user_ids))print(unique_ids) # [101, 102, 103, 105]
场景 2:找两组数据的共同项
# 一班参加数学竞赛的同学class1 = {"小明", "小红", "小刚", "小丽"}# 二班参加数学竞赛的同学class2 = {"小刚", "小丽", "小强", "小美"}# 两个班都参加的同学both = class1 & class2print("两个班都参加的:", both) # {'小刚', '小丽'}# 只在一班参加的only_class1 = class1 - class2print("只在一班的:", only_class1) # {'小明', '小红'}
场景 3:标签去重
用户打标签时,重复添加的标签自动去重,非常适合用集合存储。
八、拓展:冰冻集合 frozenset(了解即可)
普通集合 set 是可变的(能增删元素),frozenset 是不可变的集合,创建后不能增删改,相当于 “元组版的集合”。
# 创建冰冻集合fs = frozenset([1, 2, 3, 2])print(fs) # frozenset({1, 2, 3})# ❌ 不能添加、删除元素# fs.add(4) # 报错
主要用途:当字典的键、当集合的元素(需要不可变的场景)。