前言
在Python中,列表list、元组tuple、字典dict大家用得最多,但set集合常常被忽略。集合最大两个特性:
- 支持数学里全套集合运算:交集、并集、差集、对称差集、子集、超集判断。
日常场景:数据去重、两批数据对比、筛选共同/独有数据、权限匹配、标签筛选等,用集合运算一行代码搞定,比循环判断简洁几十倍。
本文分4大块:集合基础创建 → 4大核心集合运算 → 子集/超集/相等判断 → 常用内置方法 + 完整可运行案例
一、Set集合基础创建与特性
1. 创建集合两种方式
# 方式1:大括号{},元素逗号分隔
s1 = {1, 2, 3, 4, 5}
print(s1) # {1,2,3,4,5}
# 方式2:set()构造函数,接收可迭代对象(列表/字符串/元组)
s2 = set([2, 4, 6, 8, 10])
print(s2) # {2,4,6,8,10}
# 空集合注意:不能用{},{}是空字典,空集合必须 set()
empty_set = set()
print(type(empty_set)) # <class 'set'>
empty_dict = {}
print(type(empty_dict)) # <class 'dict'>
2. 核心特性:自动去重
集合不允许重复元素,写入重复值会自动丢弃:
# 列表有重复数字
lst = [1, 1, 2, 2, 3, 3, 3]
# 转集合一键去重
s = set(lst)
print(s) # {1, 2, 3}
# 字符串去重案例
str_set = set("aabbccddeeff")
print(str_set) # {'a','b','c','d','e','f'}
3. 限制:元素必须不可变
集合内不能放列表、字典这类可变对象,数字、字符串、元组可以:
# 合法
s_ok = {1, "python", (10, 20)}
# 报错!list可变,不能放入集合
# s_err = {1, [2,3]}
二、四大核心集合运算(重点)
现有两组数据作为统一测试样本,全程复用:
# 集合A:1~5
A = {1, 2, 3, 4, 5}
# 集合B:2,4,6,8,10
B = {2, 4, 6, 8, 10}
运算1:并集 | (合并所有元素,自动去重)
数学含义:把A、B所有元素合并,重复只保留一份 两种写法:| 运算符 / union() 方法
# 写法1:运算符 |
res1 = A | B
# 写法2:内置方法 union()
res2 = A.union(B)
print("并集结果:", res1)
# 输出:{1, 2, 3, 4, 5, 6, 8, 10}
print(res1 == res2) # True,两种写法完全等价
实用场景:合并两个用户标签、合并两份数据源、整合多文件ID。
运算2:交集 & (只保留两者共同存在的元素)
数学含义:同时在A和B中出现的元素 两种写法:& / intersection()
res1 = A & B
res2 = A.intersection(B)
print("交集结果:", res1)
# 输出:{2, 4}
实用场景:找出两个班级共同学生、两款商品共有的标签、同时满足两个条件的数据。
运算3:差集 - (属于A但不属于B的独有元素)
数学含义:A独有的元素,分A-B、B-A两种,不能互换 两种写法:- / difference()
# A-B:只在A,不在B
diff1 = A - B
diff1_fun = A.difference(B)
print("A独有的元素:", diff1) # {1, 3, 5}
# B-A:只在B,不在A
diff2 = B - A
diff2_fun = B.difference(A)
print("B独有的元素:", diff2) # {6, 8, 10}
实用场景:找出只买A商品没买B的客户、新增数据、删除数据对比。
运算4:对称差集 ^ (两者各自独有的元素合集,去掉公共部分)
数学含义:A独有 + B独有,排除交集 两种写法:^ / symmetric_difference()
res1 = A ^ B
res2 = A.symmetric_difference(B)
print("对称差集:", res1)
# 输出:{1, 3, 5, 6, 8, 10}
等价公式:A ^ B = (A - B) | (B - A)
实用场景:对比两份列表找出全部不一样的数据、新旧版本差异对比。
四大运算汇总对照表
| | | |
|---|
| A | B | A.union(B) | |
| A & B | A.intersection(B) | |
| A - B | A.difference(B) | |
| A ^ B | A.symmetric_difference(B) | |
三、子集、超集、相等判断(布尔返回)
依然使用样本 A={1,2,3,4,5},新增小集合 C={2,4}
1. 子集判断 <= / issubset()
C <= A:C所有元素都在A中,C是A的子集
print(C <= A) # True
print(C.issubset(A)) # True
# 反向 A <= C 不成立
print(A <= C) # False
2. 真子集 <
完全包含且不相等
print(C < A) # True
print(A < A) # False(相等不算真子集)
3. 超集 >= / issuperset()
A包含C,A是C的超集
print(A >= C)
print(A.issuperset(C)) # True
4. 真超集 >
print(A > C) # True
print(C > A) # False
5. 集合相等 ==
元素完全一致才相等,顺序无关(集合无序)
s_x = {1, 3, 5}
s_y = {5, 1, 3}
print(s_x == s_y) # True
6. 判断无交集 isdisjoint()
两个集合没有任何共同元素返回True
D = {7,9,11}
print(A.isdisjoint(D)) # True,A和D无重叠
print(A.isdisjoint(B)) # False,存在2、4交集
四、集合原地修改运算(直接改变原集合)
上面所有运算都会生成新集合,不修改原数据;下面带=的运算符直接修改自身,无返回值。
A = {1,2,3,4,5}
B = {2,4,6}
# 1. 原地并集 |= update()
A |= B
print(A) # {1,2,3,4,5,6}
# 重置A
A = {1,2,3,4,5}
A.update(B)
print(A)
# 2. 原地交集 &= intersection_update()
A = {1,2,3,4,5}
A &= B
print(A) # {2,4}
# 3. 原地差集 -= difference_update()
A = {1,2,3,4,5}
A -= B
print(A) # {1,3,5}
# 4. 原地对称差集 ^= symmetric_difference_update()
A = {1,2,3,4,5}
A ^= B
print(A) # {1,3,5,6}
五、实战综合案例
案例1:列表一键去重(最常用)
# 原始带重复数据
user_ids = [101, 102, 101, 103, 102, 104]
# 转集合去重,再转回列表
unique_ids = list(set(user_ids))
print(unique_ids)
# 注意:集合无序,若要保留原有顺序Python3.7+可用:
from collections import OrderedDict
unique_order = list(OrderedDict.fromkeys(user_ids))
print(unique_order)
案例2:找出两个列表共同好友
friends_zhang = ["小明", "小红", "小李", "小张"]
friends_li = ["小红", "小王", "小张", "小赵"]
# 转集合求交集
common = set(friends_zhang) & set(friends_li)
print("共同好友:", common)
# 输出:{'小红', '小张'}
案例3:对比新旧用户,找出新增/流失用户
old_users = {1, 2, 3, 4}
new_users = {3, 4, 5, 6}
add = new_users - old_users # 新增用户 {5,6}
lose = old_users - new_users # 流失用户 {1,2}
diff_all = old_users ^ new_users # 所有有变动用户
print("新增用户:", add)
print("流失用户:", lose)
print("变动用户总集合:", diff_all)
案例4:标签筛选,同时拥有两个标签的商品
tag_electronic = {"phone", "pad", "watch"}
tag_sale = {"phone", "earphone", "pad"}
# 既是电子产品又在促销的商品
sale_electric = tag_electronic & tag_sale
print(sale_electric) # {'phone', 'pad'}
六、Set常用增删查方法补充
1. 添加元素 add() / update()
s = {1,2,3}
s.add(4) # 添加单个元素
s.update([5,6]) # 添加多个可迭代元素
print(s) # {1,2,3,4,5,6}
2. 删除元素三方法
s = {1,2,3,4}
s.remove(2) # 删除指定元素,不存在则报错
s.discard(99) # 删除,不存在不报错(推荐)
s.pop() # 随机删除一个元素并返回
s.clear() # 清空集合
3. 判断元素是否存在 in
s = {10,20,30}
print(10in s) # True
print(99in s) # False
七、文末总结
- 集合
set核心优势:自动去重、原生支持数学集合运算,数据对比效率远高于列表循环; - 四大运算记口诀:
|合并 &取共 -独有 ^双向差异; - 区分普通运算(生成新集合)和原地
|=/-=运算(修改自身); - 适用场景:数据去重、两组数据差异对比、共同数据筛选、标签/权限匹配;
- 局限:无序、不能存可变类型(列表、字典),需要有序去重需搭配
OrderedDict。
完整代码可直接复制运行,工作中处理批量数据对比时,优先使用集合替代多层for循环,代码更简洁、执行速度更快。