Python 集合(Set)CURD 操作详解
本文聚焦 Python 集合的四大基础操作:增(Create)、查(Read)、删(Delete)、改(Update),包含详细示例与时间复杂度分析。
Python 集合(Set)是内置无序可变容器类型,支持自动去重。本文详细讲解了集合的增删改查(CURD)操作,包括创建空集合、添加元素、批量更新、成员检测、遍历及关系判断。同时深入分析了各操作的时间复杂度,并涵盖了集合间的交并差补运算及其原地修改方法。通过对比运算符与方法,提供了实际应用场景示例,帮助开发者高效掌握 Python 集合的使用技巧与性能特征。

本文聚焦 Python 集合的四大基础操作:增(Create)、查(Read)、删(Delete)、改(Update),包含详细示例与时间复杂度分析。
# 空集合(注意:不能用 {} 创建空集合)
empty = set()
type(empty) # <class 'set'>
# {} 实际上是空字典
not_empty = {}
type(not_empty) # <class 'dict'>
# 从可迭代对象创建
nums = set([1, 2, 3, 2, 1]) # {1, 2, 3} - 自动去重
# 从字符串创建
chars = set("hello") # {'h', 'e', 'l', 'o'} - 去重,顺序不定
# 直接创建(花括号语法)
colors = {"red", "green", "blue"}
# 创建单元素集合
single = {1,} # {1}
# 从范围创建
range_set = set(range(5)) # {0, 1, 2, 3, 4}
时间复杂度:
set(iterable)为 O(n),n 为可迭代对象长度
add()s = {1, 2, 3}
# 添加元素
s.add(4) # {1, 2, 3, 4}
# 添加已存在的元素(无效果,不报错)
s.add(3) # {1, 2, 3, 4}
# 添加不同类型
s.add("hello")
s.add((1, 2))
s.add(3.14)
# {1, 2, 3, 4, 'hello', (1, 2), 3.14}
# ⚠️ 无法添加不可哈希元素
# s.add([1, 2]) # TypeError: unhashable type: 'list'
# s.add({1, 2}) # TypeError: unhashable type: 'set'
时间复杂度:
add(x)为 O(1)(平均情况)
update()s = {1, 2, 3}
# 添加列表中的元素
s.update([4, 5, 6]) # {1, 2, 3, 4, 5, 6}
# 添加另一个集合
s.update({7, 8, 9}) # {1, 2, 3, 4, 5, 6, 7, 8, 9}
# 添加字符串(逐字符添加)
s.update("abc") # {1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c'}
# 添加元组
s.update((10, 11)) # {1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 10, 11}
# 添加范围
s.update(range(12, 15)) # {1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 10, 11, 12, 13, 14}
# update 等价于 |= 运算符
s |= {15, 16} # {1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 10, 11, 12, 13, 14, 15, 16}
时间复杂度:
update(iter)为 O(k),k 为添加的元素数量
ins = {"apple", "banana", "cherry"}
# in 运算符
"apple" in s # True
"grape" in s # False
# not in 运算符
"orange" not in s # True
# 检测数字
nums = {1, 2, 3, 4, 5}
3 in nums # True
10 in nums # False
# 检测元组(元组可哈希)
points = {(0, 0), (1, 1), (2, 2)}
(1, 1) in points # True
(3, 3) in points # False
时间复杂度:
x in s为 O(1)(平均情况)
len()s = {1, 2, 3, 4, 5}
# len() 函数
len(s) # 5
# 空集合
len(set()) # 0
# 去重后的数量
lst = [1, 2, 2, 3, 3, 3]
len(set(lst)) # 3
时间复杂度:
len(s)为 O(1)
s = {"a", "b", "c", "d"}
# for 循环遍历
for item in s:
print(item)
# 注意:集合无序,输出顺序不确定
# 使用 enumerate 获取索引
for i, item in enumerate(s):
print(f"{i}: {item}")
# 0: a
# 1: b
# 2: c
# 3: d
# (顺序可能不同)
# 遍历数字集合
nums = {10, 20, 30, 40, 50}
for num in nums:
print(num * 2)
# 20, 40, 60, 80, 100(顺序可能不同)
时间复杂度:遍历为 O(n),n 为集合大小
set_a = {1, 2, 3}
set_b = {1, 2, 3, 4, 5}
set_c = {1, 2}
# issubset(): 是否子集
set_c.issubset(set_a) # True
set_c.issubset(set_b) # True
# <= 运算符:子集(包含自身)
set_c <= set_a # True
set_a <= set_a # True
# < 运算符:真子集(不包含自身)
set_c < set_a # True
set_a < set_a # False
# issuperset(): 是否超集
set_b.issuperset(set_a) # True
set_a.issuperset(set_c) # True
# >= 运算符:超集(包含自身)
set_b >= set_a # True
set_a >= set_a # True
# > 运算符:真超集(不包含自身)
set_b > set_a # True
set_a > set_a # False
# isdisjoint(): 是否无交集
{1, 2}.isdisjoint({3, 4}) # True
{1, 2}.isdisjoint({2, 3}) # False
时间复杂度:关系检查为 O(min(len(s1), len(s2)))
s = {1, 2, 3, 4, 5}
# copy() 方法:浅拷贝
s_copy = s.copy() # {1, 2, 3, 4, 5}
# 修改原集合不影响副本
s.add(6)
print(s) # {1, 2, 3, 4, 5, 6}
print(s_copy) # {1, 2, 3, 4, 5}
# 等价于 set() 构造函数
s_copy2 = set(s)
时间复杂度:
copy()为 O(n)
remove()s = {1, 2, 3, 4, 5}
# 删除元素
s.remove(3) # {1, 2, 4, 5}
# 删除多个
s.remove(1)
s.remove(5) # {2, 4}
# ⚠️ 元素不存在时抛出 KeyError
# s.remove(10) # KeyError: 10
# 安全删除:先检查
if 10 in s:
s.remove(10)
else:
print("10 不在集合中")
时间复杂度:
remove(x)为 O(1)(元素存在时)
discard()s = {1, 2, 3, 4, 5}
# 删除存在的元素
s.discard(3) # {1, 2, 4, 5}
# 删除不存在的元素(不报错)
s.discard(10) # {1, 2, 4, 5}
# 连续删除
s.discard(1)
s.discard(2)
s.discard(100) # 不存在,也不报错
# {4, 5}
时间复杂度:
discard(x)为 O(1)
pop()s = {1, 2, 3, 4, 5}
# 删除并返回任意元素
element = s.pop()
print(element) # 可能是 1、2、3、4、5 中的任意一个
print(s) # 剩余 4 个元素
# 连续弹出
while s:
elem = s.pop()
print(f"弹出:{elem}, 剩余:{s}")
# 空集合调用 pop 抛出 KeyError
# set().pop() # KeyError: pop from an empty set
注意:集合无序,
pop()删除的是"任意"元素,不是特定位置时间复杂度:
pop()为 O(1)
clear()s = {1, 2, 3, 4, 5}
# 清空所有元素
s.clear()
print(s) # set()
# 验证清空后为空
len(s) # 0
# 重新赋值
s = {1, 2, 3}
s.clear()
s # set()
时间复杂度:
clear()为 O(1)
s = {1, 2, 3, 4, 5, 6, 7, 8, 9}
# difference_update(): 删除多个元素
s.difference_update({2, 4, 6, 8}) # {1, 3, 5, 7, 9}
# 等价于 -= 运算符
s -= {1, 9} # {3, 5, 7}
# 保留指定元素(删除不在指定集合中的元素)
s.intersection_update({3, 4, 5}) # {3, 5}
# 保留奇数
odd_set = {1, 3, 5, 7, 9}
s = {1, 2, 3, 4, 5, 6, 7, 8, 9}
s.intersection_update(odd_set) # {1, 3, 5, 7, 9}
时间复杂度:批量删除为 O(len(s_to_remove))
集合本身是无序的,没有"修改特定位置元素"的概念。
但可以通过"删除 + 添加"的方式改变集合内容:
s = {1, 2, 3, 4, 5}
# 方式:先删除,再添加
s.discard(3)
s.add(30) # {1, 2, 4, 5, 30}
# 替换多个值
s.discard(1)
s.discard(2)
s.add(10)
s.add(20) # {4, 5, 30, 10, 20}
s = {1, 2, 3, 4, 5}
# 并集:添加多个元素
s = s | {10, 20, 30} # {1, 2, 3, 4, 5, 10, 20, 30}
# 交集:只保留指定元素
s = s & {2, 4, 6, 8} # {2, 4}
# 差集:删除指定元素
s = s - {4} # {2}
# 对称差:保留不共有的元素
s = s ^ {2, 3, 4} # {3, 4}
a = {1, 2, 3}
b = {3, 4, 5}
# 原地并集(修改 a)
a |= b
print(a) # {1, 2, 3, 4, 5}
# 原地交集
a &= {2, 4, 6}
print(a) # {2, 4}
# 原地差集
a -= {4}
print(a) # {2}
# 原地对称差
a ^= {2, 3, 4}
print(a) # {3, 4}
a = {1, 2, 3}
b = {3, 4, 5}
c = {5, 6, 7}
# union() 方法
result = a.union(b) # {1, 2, 3, 4, 5}
# | 运算符
result = a | b # {1, 2, 3, 4, 5}
# 多个集合的并集
result = a | b | c # {1, 2, 3, 4, 5, 6, 7}
result = a.union(b, c) # {1, 2, 3, 4, 5, 6, 7}
时间复杂度:O(len(a) + len(b))
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
c = {4, 5, 6}
# intersection() 方法
result = a.intersection(b) # {3, 4}
# & 运算符
result = a & b # {3, 4}
# 多个集合的交集
result = a & b & c # {4}
result = a.intersection(b, c) # {4}
时间复杂度:O(min(len(a), len(b)))
a = {1, 2, 3, 4, 5}
b = {4, 5, 6, 7}
# difference() 方法:a 有但 b 没有的
result = a.difference(b) # {1, 2, 3}
# - 运算符
result = a - b # {1, 2, 3}
# 反向差集:b 有但 a 没有的
result = b - a # {6, 7}
# ⚠️ 差集不满足交换律
print(a - b == b - a) # False(通常)
时间复杂度:O(len(a))
对称差:返回只在一个集合中出现的元素,即"非共有"元素。
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
# symmetric_difference() 方法
result = a.symmetric_difference(b) # {1, 2, 5, 6}
# 解释:1,2 只在 a 中;5,6 只在 b 中;3,4 在两者中(被排除)
# ^ 运算符(更简洁)
result = a ^ b # {1, 2, 5, 6}
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
print(f"A: {a}") # {1, 2, 3, 4}
print(f"B: {b}") # {3, 4, 5, 6}
print(f"并集:{a | b}") # {1, 2, 3, 4, 5, 6} - 所有元素
print(f"交集:{a & b}") # {3, 4} - 共有元素
print(f"差集:{a - b}") # {1, 2} - a 有 b 没有
print(f"差集:{b - a}") # {5, 6} - b 有 a 没有
print(f"对称差:{a ^ b}") # {1, 2, 5, 6} - 只在一个集合中
# 对称差 = 并集 - 交集
result = (a | b) - (a & b) # {1, 2, 5, 6}
# 对称差 = (a-b) 的并集 (b-a)
result = (a - b) | (b - a) # {1, 2, 5, 6}
# 1. 找出变化:比较新旧版本
old_version = {"a", "b", "c", "d"}
new_version = {"b", "c", "e", "f"}
# 所有变化的项(新增 + 删除)
changed = old_version ^ new_version # {'a', 'd', 'e', 'f'}
# a, d 是删除的;e, f 是新增的
# 2. 找出独有元素
group_a = {"苹果", "香蕉", "橙子"}
group_b = {"香蕉", "葡萄", "西瓜"}
# 只在一个组中出现的水果
exclusive = group_a ^ group_b # {'苹果', '橙子', '葡萄', '西瓜'}
# 香蕉在两组都有,所以不在结果中
# 3. 比较两个集合的差异
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}
# 找出不同的元素
different = set1 ^ set2 # {1, 2, 3, 6, 7, 8}
# 4. 多个集合的对称差
a = {1, 2}
b = {2, 3}
c = {3, 4}
# 链式对称差
result = a ^ b ^ c # {1, 4}
# 解释:出现奇数次的元素保留,出现偶数次的去除
# 1 出现 1 次 → 保留
# 2 出现 2 次 → 去除
# 3 出现 2 次 → 去除
# 4 出现 1 次 → 保留
a = {1, 2, 3, 4}
# 原地修改 a
a ^= {3, 4, 5, 6} # a: {1, 2, 5, 6}
# 等价于 a.symmetric_difference_update({3, 4, 5, 6})
时间复杂度:O(len(a) + len(b))
| 运算 | 方法 | 运算符 | 描述 | 返回新集合 | 原地运算符 |
|---|---|---|---|---|---|
| 并集 | union() | ` | ` (竖线) | 两集合所有元素 | ✅ |
| 交集 | intersection() | & (且号) | 两集合共有的元素 | ✅ | &= |
| 差集 | difference() | - (减号) | a 有但 b 没有的 | ✅ | -= |
| 对称差 | symmetric_difference() | ^ (脱字符) | 只在一个集合中的 | ✅ | ^= |
运算符说明:
|:并集(键盘上 Enter 键上方的那个键)&:交集(Shift + 7)^:对称差(Shift + 6)-:差集(减号)# 快速示例
a = {1, 2}
b = {2, 3}
a | b # {1, 2, 3} 并集
a & b # {2} 交集
a - b # {1} 差集
a ^ b # {1, 3} 对称差
a = {1, 2, 3}
b = {3, 4, 5}
# 原地并集(a |= b 修改 a,不返回新集合)
a |= b # a: {1, 2, 3, 4, 5}
# 等价于 a.update(b)
# 原地交集
a &= {2, 4, 6} # a: {2, 4}
# 等价于 a.intersection_update({2, 4, 6})
# 原地差集
a -= {4} # a: {2}
# 等价于 a.difference_update({4})
# 原地对称差
a ^= {2, 3, 4} # a: {3, 4}
# 等价于 a.symmetric_difference_update({2, 3, 4})
优势:原地运算符更高效,不创建新集合
| 操作 | 方法/运算符 | 平均复杂度 | 说明 |
|---|---|---|---|
| 创建 | set(iterable) | O(n) | n 为可迭代对象长度 |
| 添加 | add(x) | O(1) | 均摊 |
| 批量添加 | update(iter) | O(k) | k 为添加长度 |
| 成员检测 | x in s | O(1) | 平均 |
| 长度 | len(s) | O(1) | |
| 删除 | remove(x) | O(1) | 元素存在时 |
| 安全删除 | discard(x) | O(1) | |
| 弹出 | pop() | O(1) | 删除任意元素 |
| 清空 | clear() | O(1) | |
| 复制 | copy() | O(n) | n 为集合大小 |
| 遍历 | for x in s | O(n) | n 为集合大小 |
| 并集 | `s1 | s2` | O(m+n) |
| 交集 | s1 & s2 | O(min(m,n)) | 遍历较小集合 |
| 差集 | s1 - s2 | O(m) | m 为 s1 长度 |
| 对称差 | s1 ^ s2 | O(m+n) | m, n 为两集合长度 |
| 关系检查 | issubset/issuperset | O(min(m,n)) | 子集/超集检查 |
| 操作类别 | 方法/运算符 | 要点 |
|---|---|---|
| 创建 | set(), {} | set() 创建空集合,{} 创建空字典 |
| 添加 | add(), update() | add() 单个 O(1),update() 批量 O(k) |
| 删除 | remove(), discard(), pop(), clear() | remove() 元素不存在报错,discard() 不报错 |
| 查询 | in, len(), 遍历 | in 检测 O(1),len() O(1) |
| 关系 | issubset(), issuperset(), isdisjoint() | 子集/超集/无交集判断 |
| 并集 | ` | , union()` |
| 交集 | &, intersection() | 两集合共有元素 |
| 差集 | -, difference() | a 有 b 没有 |
| 对称差 | ^, symmetric_difference() | 只在一个集合中 |
| 原地运算 | ` | =, &=, -=, ^=` |

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online