【Python】集合(Set)
目录
4.4 对称差集(Symmetric Difference)
文档介绍
Python 中的集合(Set)是一种无序、可变的序列数据类型,其核心特性是元素唯一,不允许出现重复值。集合基于哈希表实现,支持交集、并集、差集等数学集合运算,是处理数据去重、成员关系判断、集合运算的高效工具。
本教程从基础认知到高级应用,全面讲解集合的语法、特性、操作及实战场景,适合Python初学者及需要巩固集合知识的开发者学习。

学习目标
-
掌握集合的核心特性与创建方式
-
熟练运用集合的增、删、查、遍历操作
-
精通集合的数学运算(交集、并集、差集等)
-
理解集合推导式、不可变集合(frozenset)的应用
-
规避集合使用的常见误区,解决实际业务问题
第一章 集合的基础认知
1.1 集合的核心特性
集合与列表(list)、元组(tuple)、字典(dict)相比,有三大独特属性:
|
特性 |
说明 |
|---|---|
|
元素唯一 |
自动去重,同一集合中不存在重复元素,是数据去重的首选工具。 |
|
无序性 |
集合中的元素没有固定顺序,不支持索引、切片操作(与列表/元组的核心区别)。 |
|
可变性 |
集合本身可增删元素,但元素必须是不可变类型(如整数、字符串、元组)。 |
1.2 集合与其他数据类型的对比
为了更清晰理解集合,我们将其与常用数据类型对比:
|
数据类型 |
是否有序 |
是否可变 |
元素是否可重复 |
元素类型要求 |
核心用途 |
|---|---|---|---|---|---|
|
列表(list) |
是 |
是 |
是 |
任意类型 |
存储有序序列、增删改查 |
|
元组(tuple) |
是 |
否 |
是 |
任意类型 |
存储不可变有序序列 |
|
字典(dict) |
否(3.7+有序) |
是 |
键唯一、值可重复 |
键必须不可变,值任意 |
存储键值对映射 |
|
集合(set) |
否 |
是 |
否(自动去重) |
必须不可变类型 |
数据去重、集合运算 |
1.3 集合的适用场景
-
数据去重:快速去除列表、元组中的重复元素
-
成员关系判断:判断某个元素是否在集合中,效率远高于列表
-
集合运算:实现数学中的交集、并集、差集、子集判断等逻辑
-
高效存储:哈希表实现的集合,查询、插入、删除的时间复杂度均为O(1)
第二章 集合的创建
集合的创建主要有两种方式:直接用花括号{}和使用set()函数,需注意空集合的创建细节。
2.1 直接创建集合(花括号{})
语法:集合名 = {元素1, 元素2, 元素3, ...}
-
元素必须是不可变类型(int、float、str、tuple、bool等),不能是list、dict、set等可变类型
-
自动去重:重复元素会被自动剔除
示例代码:
# 1. 创建空集合?(错误示范) empty_set = {} # 这是**空字典**,不是空集合! print(type(empty_set)) # 输出:<class 'dict'> # 2. 创建非空集合 # 元素为整数、字符串、元组(不可变类型) num_set = {1, 2, 3, 4, 4, 5} # 自动去重,重复的4被剔除 str_set = {"Python", "Java", "Python"} tuple_set = {(1, 2), (3, 4), (1, 2)} # 元组是不可变类型,可作为集合元素 # 3. 错误示例:元素包含可变类型(列表) # error_set = {1, 2, [3, 4]} # 报错:TypeError: unhashable type: 'list' # 输出集合 print("num_set:", num_set) # 输出:{1, 2, 3, 4, 5}(无序,顺序可能不同) print("str_set:", str_set) # 输出:{'Python', 'Java'} print("tuple_set:", tuple_set) # 输出:{(1, 2), (3, 4)}
2.2 使用set()函数创建
set()函数可将可迭代对象(列表、元组、字符串、range等)转换为集合,同样会自动去重。
语法:集合名 = set(可迭代对象)
示例代码:
# 1. 从列表创建集合(自动去重) list1 = [1, 2, 2, 3, 4, 4] set1 = set(list1) print("set1:", set1) # 输出:{1, 2, 3, 4} # 2. 从字符串创建集合(按字符拆分,去重) str1 = "hello" set2 = set(str1) print("set2:", set2) # 输出:{'h', 'e', 'l', 'o'}(l重复,仅保留一个) # 3. 从元组创建集合 tuple1 = (5, 6, 6, 7) set3 = set(tuple1) print("set3:", set3) # 输出:{5, 6, 7} # 4. 创建空集合(正确方式) empty_set = set() print(type(empty_set)) # 输出:<class 'set'>
2.3 关键注意事项
-
空集合必须用set()创建:
{}是空字典,不是空集合 -
元素必须可哈希:集合元素需满足“可哈希”(不可变),否则会触发
TypeError -
集合无序:输出顺序与创建顺序无关,不能通过索引访问元素(如
num_set[0]会报错)
第三章 集合的基本操作
集合是可变的,支持添加元素、删除元素、查询元素、遍历集合等基本操作,以下逐一讲解。
3.1 添加元素
集合提供两种添加元素的方法:add()(添加单个元素)和update()(添加多个元素)。
3.1.1 add():添加单个元素
语法:集合.add(元素)
-
元素必须是不可变类型
-
若元素已存在,不执行任何操作(自动去重)
示例代码:
# 创建空集合 num_set = set() # 添加单个整数 num_set.add(1) num_set.add(2) print("添加1、2后:", num_set) # 输出:{1, 2} # 添加重复元素(无效果) num_set.add(1) print("添加重复元素1后:", num_set) # 输出:{1, 2} # 添加不可变类型元素(元组) num_set.add((3, 4)) print("添加元组后:", num_set) # 输出:{1, 2, (3, 4)} # 错误:添加可变类型元素(列表) # num_set.add([5, 6]) # 报错:TypeError: unhashable type: 'list'
3.1.2 update():添加多个元素
语法:集合.update(可迭代对象)
-
参数必须是可迭代对象(列表、元组、字符串、集合等)
-
会将可迭代对象的每个元素逐一添加到集合中,自动去重
示例代码:
num_set = {1, 2} # 1. 从列表添加多个元素 num_set.update([3, 4, 4]) # 列表中的4会被去重 print("从列表添加后:", num_set) # 输出:{1, 2, 3, 4} # 2. 从字符串添加多个元素(按字符拆分) num_set.update("56") print("从字符串添加后:", num_set) # 输出:{1, 2, 3, 4, '5', '6'} # 3. 从集合添加多个元素 num_set.update({7, 8}) print("从集合添加后:", num_set) # 输出:{1, 2, 3, 4, '5', '6', 7, 8}
3.2 删除元素
集合的删除操作有四种方法:remove()、discard()、pop()、clear(),需注意各自的差异。
3.2.1 remove():删除指定元素
语法:集合.remove(元素)
-
若元素不存在,会直接抛出
KeyError异常 -
必须指定要删除的元素(无返回值)
示例代码:
num_set = {1, 2, 3, 4} # 1. 删除存在的元素 num_set.remove(2) print("删除2后:", num_set) # 输出:{1, 3, 4} # 2. 删除不存在的元素(报错) # num_set.remove(5) # 报错:KeyError: 5
3.2.2 discard():删除指定元素(安全)
语法:集合.discard(元素)
-
若元素不存在,不会报错,直接忽略操作
-
相比
remove()更安全,适合不确定元素是否存在的场景
示例代码:
num_set = {1, 2, 3, 4} # 1. 删除存在的元素 num_set.discard(3) print("删除3后:", num_set) # 输出:{1, 2, 4} # 2. 删除不存在的元素(无报错) num_set.discard(5) print("删除不存在的5后:", num_set) # 输出:{1, 2, 4}
3.2.3 pop():随机删除并返回元素
语法:集合.pop()
-
集合是无序的,因此
pop()会随机删除并返回集合中的一个元素 -
若集合为空,会抛出
KeyError异常
示例代码:
num_set = {1, 2, 3, 4} # 随机删除并返回元素 deleted_elem = num_set.pop() print("随机删除的元素:", deleted_elem) # 输出:1(或其他元素,随机) print("删除后集合:", num_set) # 输出:{2, 3, 4}(或其他剩余元素) # 空集合调用pop()(报错) # empty_set = set() # empty_set.pop() # 报错:KeyError: 'pop from an empty set'
3.2.4 clear():清空集合
语法:集合.clear()
-
无参数、无返回值,直接清空集合中的所有元素,集合变为空集合(但集合对象仍存在)
示例代码:
num_set = {1, 2, 3, 4} # 清空集合 num_set.clear() print("清空后集合:", num_set) # 输出:set() print("集合类型:", type(num_set)) # 输出:<class 'set'>
3.3 查询元素(成员关系判断)
集合不支持索引访问,因此判断元素是否存在是核心查询操作,使用in和not in关键字。
语法:
-
元素 in 集合:若元素存在,返回True,否则返回False -
元素 not in 集合:若元素不存在,返回True,否则返回False
示例代码:
num_set = {1, 2, 3, 4} # 1. 判断元素存在 print(2 in num_set) # 输出:True print(5 in num_set) # 输出:False # 2. 判断元素不存在 print(5 not in num_set) # 输出:True print(2 not in num_set) # 输出:False # 3. 结合条件语句使用 if 3 in num_set: print("3在集合中,执行删除操作") num_set.remove(3) print("删除3后:", num_set) # 输出:{1, 2, 4}
3.4 遍历集合
由于集合无序,遍历只能通过for循环实现,无法通过索引遍历。
语法:for 元素 in 集合: 操作元素
示例代码:
num_set = {1, 2, 3, 4, 5} # 1. 基础遍历 print("集合元素遍历:") for num in num_set: print(num, end=" ") # 输出:1 2 3 4 5(顺序可能不同) # 2. 遍历并处理元素 print("\n遍历并计算平方:") for num in num_set: print(f"{num}的平方是{num**2}", end=" | ") # 输出:1的平方是1 | 2的平方是4 | ...
第四章 集合的核心数学运算
集合的核心价值在于支持数学集合运算,Python提供了运算符和方法两种实现方式,功能完全一致,仅语法不同。
4.1 交集(Intersection)
交集表示两个集合中共同存在的元素,用&运算符或intersection()方法实现。
语法与示例:
-
运算符:
集合1 & 集合2(返回新集合,不修改原集合) -
方法:
集合1.intersection(集合2)(返回新集合,不修改原集合)
# 定义两个集合 set_a = {1, 2, 3, 4} set_b = {3, 4, 5, 6} # 用运算符求交集 intersection1 = set_a & set_b print("运算符求交集:", intersection1) # 输出:{3, 4} # 用方法求交集 intersection2 = set_a.intersection(set_b) print("方法求交集:", intersection2) # 输出:{3, 4} # 原集合不变 print("原set_a:", set_a) # 输出:{1, 2, 3, 4} print("原set_b:", set_b) # 输出:{3, 4, 5, 6}
4.2 并集(Union)
并集表示两个集合中所有的元素(去重后),用|运算符或union()方法实现。
语法与示例:
-
运算符:
集合1 | 集合2(返回新集合,不修改原集合) -
方法:
集合1.union(集合2)(返回新集合,不修改原集合)
set_a = {1, 2, 3, 4} set_b = {3, 4, 5, 6} # 运算符求并集 union1 = set_a | set_b print("运算符求并集:", union1) # 输出:{1, 2, 3, 4, 5, 6} # 方法求并集 union2 = set_a.union(set_b) print("方法求并集:", union2) # 输出:{1, 2, 3, 4, 5, 6}
4.3 差集(Difference)
差集表示集合1中存在、但集合2中不存在的元素,用-运算符或difference()方法实现(顺序影响结果)。
语法与示例:
-
运算符:
集合1 - 集合2(返回新集合,不修改原集合) -
方法:
集合1.difference(集合2)(返回新集合,不修改原集合)
set_a = {1, 2, 3, 4} set_b = {3, 4, 5, 6} # 集合a - 集合b(a有、b没有) diff1 = set_a - set_b print("set_a - set_b:", diff1) # 输出:{1, 2} # 集合b - 集合a(b有、a没有) diff2 = set_b - set_a print("set_b - set_a:", diff2) # 输出:{5, 6} # 方法实现 diff3 = set_a.difference(set_b) print("方法实现差集:", diff3) # 输出:{1, 2}
4.4 对称差集(Symmetric Difference)
对称差集表示两个集合中互不相同的元素(即并集减去交集),用^运算符或symmetric_difference()方法实现。
语法与示例:
-
运算符:
集合1 ^ 集合2(返回新集合,不修改原集合) -
方法:
集合1.symmetric_difference(集合2)(返回新集合,不修改原集合)
set_a = {1, 2, 3, 4} set_b = {3, 4, 5, 6} # 运算符求对称差集 sym_diff1 = set_a ^ set_b print("运算符求对称差集:", sym_diff1) # 输出:{1, 2, 5, 6} # 方法求对称差集 sym_diff2 = set_a.symmetric_difference(set_b) print("方法求对称差集:", sym_diff2) # 输出:{1, 2, 5, 6} # 等价于:并集 - 交集 sym_diff3 = (set_a | set_b) - (set_a & set_b) print("等价运算结果:", sym_diff3) # 输出:{1, 2, 5, 6}
4.5 子集与超集判断
若集合1的所有元素都在集合2中,则集合1是集合2的子集,集合2是集合1的超集,用<=(子集)、>=(超集)运算符或对应方法实现。
核心语法:
-
子集:
集合1 <= 集合2或集合1.issubset(集合2) -
真子集(集合1≠集合2):
集合1 < 集合2 -
超集:
集合1 >= 集合2或集合1.issuperset(集合2) -
真超集(集合1≠集合2):
集合1 > 集合2
set1 = {1, 2, 3} set2 = {1, 2, 3, 4, 5} set3 = {1, 2, 3} # 子集判断 print("set1是set2的子集?", set1 <= set2) # 输出:True print("set1是set2的真子集?", set1 < set2) # 输出:True print("set1是set3的子集?", set1.issubset(set3)) # 输出:True print("set1是set3的真子集?", set1 < set3) # 输出:False(两集合相等) # 超集判断 print("set2是set1的超集?", set2 >= set1) # 输出:True print("set2是set1的真超集?", set2 > set1) # 输出:True print("set3是set1的超集?", set3.issuperset(set1)) # 输出:True
第五章 集合的高级应用
5.1 集合推导式
集合推导式与列表推导式类似,用于快速创建集合,语法更简洁,且自动去重。
语法:{表达式 for 变量 in 可迭代对象 if 条件}
示例代码:
# 1. 基础推导式:创建1-10的偶数集合 even_set = {x for x in range(1, 11) if x % 2 == 0} print("偶数集合:", even_set) # 输出:{2, 4, 6, 8, 10} # 2. 去重功能:从列表中去重并筛选 list1 = [1, 2, 2, 3, 4, 4, 5] unique_set = {x for x in list1 if x > 2} print("去重筛选后:", unique_set) # 输出:{3, 4, 5} # 3. 复杂表达式:计算平方并去重 num_list = [1, 2, 2, 3, 3, 4] square_set = {x**2 for x in num_list} print("平方集合:", square_set) # 输出:{1, 4, 9, 16}
5.2 不可变集合(frozenset)
普通集合(set)是可变的,不能作为字典的键、也不能作为其他集合的元素;而不可变集合(frozenset)是不可变的,支持除增删外的所有集合操作,可作为字典键和集合元素。
创建方式:frozenset(可迭代对象)
示例代码:
# 创建不可变集合 f_set = frozenset({1, 2, 3, 4}) print("不可变集合:", f_set) # 输出:frozenset({1, 2, 3, 4}) print("类型:", type(f_set)) # 输出:<class 'frozenset'> # 不可变集合不能增删元素(报错) # f_set.add(5) # 报错:AttributeError: 'frozenset' object has no attribute 'add' # f_set.remove(1) # 报错:AttributeError: 'frozenset' object has no attribute 'remove' # 可进行集合运算 set1 = {3, 4, 5} print("交集:", f_set & set1) # 输出:{3, 4} # 可作为字典的键 dict1 = {f_set: "不可变集合作为键"} print(dict1) # 输出:{frozenset({1, 2, 3, 4}): '不可变集合作为键'} # 可作为其他集合的元素 set2 = {f_set, 5, 6} print("包含不可变集合的集合:", set2) # 输出:{5, 6, frozenset({1, 2, 3, 4})}
第六章 集合使用的常见误区与注意事项
6.1 常见误区
-
误区1:用{}创建空集合:
{}创建的是空字典,空集合必须用set()创建。 -
误区2:集合支持索引访问:集合是无序的,不支持
集合[0]这种索引操作,会抛出TypeError。 -
误区3:集合元素可以是任意类型:集合元素必须是不可变类型(可哈希),不能是列表、字典、普通集合等可变类型。
-
误区4:集合运算会修改原集合:大部分集合运算(&、|、-、^)和对应方法(intersection、union等)会返回新集合,不会修改原集合。
6.2 注意事项
-
集合的无序性:输出顺序与创建顺序无关,不同环境下输出顺序可能不同,属于正常现象。
-
效率对比:集合的成员关系判断(in)效率远高于列表,数据量越大,优势越明显(列表时间复杂度O(n),集合O(1))。
-
不可变集合的使用场景:当需要将集合作为字典键或其他集合元素时,必须使用frozenset。
-
空集合判断:判断集合是否为空,用
if not 集合名,而非if 集合名 == []或if 集合名 == {}。
第七章 实战案例
案例1:数据去重
需求:去除列表中的重复元素,保留唯一值,并返回新列表。
# 原始列表(含重复元素) student_ids = [101, 102, 103, 102, 104, 101, 105, 103] # 方法1:用set去重,再转换为列表 unique_ids1 = list(set(student_ids)) print("去重后(无序):", unique_ids1) # 输出:[101, 102, 103, 104, 105](顺序可能不同) # 方法2:去重并保留原顺序(Python 3.7+) unique_ids2 = list(dict.fromkeys(student_ids)) print("去重后(保序):", unique_ids2) # 输出:[101, 102, 103, 104, 105]
案例2:成员关系快速判断
需求:判断某个学生ID是否在已注册列表中,列表长度为10000+,要求高效判断。
import random # 生成10000个随机学生ID(可能重复) random_ids = [random.randint(1000, 9999) for _ in range(10000)] # 转换为集合(提升查询效率) id_set = set(random_ids) # 判断目标ID是否存在 target_id = 5678 if target_id in id_set: print(f"ID {target_id} 已注册") else: print(f"ID {target_id} 未注册")
案例3:集合运算实战
需求:已知两个班级的学生姓名,求两个班级的共同学生、所有学生、仅在A班的学生。
# A班和B班学生姓名 class_a = {"张三", "李四", "王五", "赵六"} class_b = {"王五", "赵六", "孙七", "周八"} # 共同学生(交集) common_students = class_a & class_b print("两个班级共同学生:", common_students) # 输出:{'王五', '赵六'} # 所有学生(并集) all_students = class_a | class_b print("两个班级所有学生:", all_students) # 输出:{'张三', '李四', '王五', '赵六', '孙七', '周八'} # 仅在A班的学生(差集) only_a = class_a - class_b print("仅在A班的学生:", only_a) # 输出:{'张三', '李四'}
总结
Python集合是一种高效、实用的数据类型,核心优势在于元素唯一、无序、支持集合运算,适用于数据去重、成员关系判断、集合逻辑运算等场景。
本教程重点讲解了集合的基础特性、创建方式、基本操作、数学运算、高级应用及实战案例,掌握这些内容后,可灵活运用集合解决实际开发中的问题。需注意区分普通集合与不可变集合的使用场景,规避常见误区,充分发挥集合的高效性。
更多推荐



所有评论(0)