1. 什么是 set
set 是 Python 内置的可变、无序、元素不重复的容器类型。它基于哈希表实现,因此判断元素是否存在、去重、集合运算都非常高效,平均时间复杂度为 O(1)。
python
# 创建集合的几种方式
s1 = {1, 2, 3}
s2 = set([1, 2, 2, 3]) # 自动去重 -> {1, 2, 3}
s3 = set("hello") # {'h', 'e', 'l', 'o'}
s4 = set() # 空集合,注意 {} 是空字典
print(s1, s2, s3, s4)
注意:
set的元素必须是**可哈希(hashable)**的,所以列表、字典、集合本身不能作为元素,而数字、字符串、元组可以。
2. 增删改查常用函数
2.1 添加元素:add / update
python
s = {1, 2, 3}
s.add(4) # 添加单个元素
s.add(2) # 已存在,不会报错,也不会重复添加
print(s) # {1, 2, 3, 4}
s.update([5, 6]) # 批量添加,可传列表、元组、集合、字符串
s.update("ab")
print(s) # {1, 2, 3, 4, 5, 6, 'a', 'b'}
2.2 删除元素:remove / discard / pop / clear
python
s = {1, 2, 3, 4}
s.remove(2) # 删除指定元素,元素不存在会抛 KeyError
print(s) # {1, 3, 4}
s.discard(100) # 删除指定元素,不存在也不报错(推荐)
print(s) # {1, 3, 4}
item = s.pop() # 随机弹出一个元素(无序,不保证是哪个)
print(item, s)
s.clear() # 清空集合
print(s) # set()
2.3 查询与长度
python
s = {"apple", "banana", "cherry"}
print("apple" in s) # True,成员判断,O(1)
print("grape" in s) # False
print(len(s)) # 3
3. 集合运算函数
集合运算既可以用运算符,也可以用方法,方法的好处是参数可以是任意可迭代对象。
python
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
# 并集
print(a | b) # {1, 2, 3, 4, 5, 6}
print(a.union(b)) # 同上
# 交集
print(a & b) # {3, 4}
print(a.intersection(b)) # 同上
# 差集(在 a 中但不在 b 中)
print(a - b) # {1, 2}
print(a.difference(b)) # 同上
# 对称差集(只在其中一个集合中)
print(a ^ b) # {1, 2, 5, 6}
print(a.symmetric_difference(b)) # 同上
3.1 原地更新版本
python
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
a.update(b) # 等价于 a |= b
print(a) # {1, 2, 3, 4, 5, 6}
a = {1, 2, 3, 4}
a.intersection_update(b) # 等价于 a &= b
print(a) # {3, 4}
a = {1, 2, 3, 4}
a.difference_update(b) # 等价于 a -= b
print(a) # {1, 2}
a = {1, 2, 3, 4}
a.symmetric_difference_update(b) # 等价于 a ^= b
print(a) # {1, 2, 5, 6}
3.2 子集与超集判断
python
a = {1, 2}
b = {1, 2, 3, 4}
print(a.issubset(b)) # True,a 是 b 的子集
print(b.issuperset(a)) # True,b 是 a 的超集
print(a.isdisjoint({5, 6})) # True,两集合无交集
4. 实战案例
4.1 列表去重并保持顺序
set 本身无序,若需要去重后保持原顺序,可以配合 dict.fromkeys:
python
nums = [3, 1, 2, 3, 1, 4, 2]
# 仅去重(顺序不保证)
print(list(set(nums))) # [1, 2, 3, 4]
# 去重且保持原顺序
print(list(dict.fromkeys(nums))) # [3, 1, 2, 4]
4.2 找出两个列表的共同元素与差异
python
list_a = ["张三", "李四", "王五", "赵六"]
list_b = ["李四", "赵六", "钱七"]
set_a, set_b = set(list_a), set(list_b)
print("共同好友:", set_a & set_b) # {'李四', '赵六'}
print("只在 A 中:", set_a - set_b) # {'张三', '王五'}
print("只在 B 中:", set_b - set_a) # {'钱七'}
print("所有好友:", set_a | set_b)
4.3 统计文本中的不重复单词
python
text = "the quick brown fox jumps over the lazy dog the fox"
words = text.split()
unique_words = set(words)
print("单词总数:", len(words)) # 11
print("不重复单词数:", len(unique_words)) # 8
print("不重复单词:", sorted(unique_words))
4.4 用集合做快速黑名单过滤
python
blacklist = {"192.168.1.1", "10.0.0.5", "172.16.0.9"}
requests = ["192.168.1.1", "8.8.8.8", "10.0.0.5", "1.1.1.1"]
allowed = [ip for ip in requests if ip not in blacklist]
print(allowed) # ['8.8.8.8', '1.1.1.1']
4.5 判断两个字符串是否为字母异位词
python
def is_anagram(s1: str, s2: str) -> bool:
return set(s1) == set(s2) and sorted(s1) == sorted(s2)
print(is_anagram("listen", "silent")) # True
print(is_anagram("hello", "world")) # False
5. 常用函数速查表
| 函数 / 方法 | 说明 | 是否原地修改 |
|---|---|---|
add(x) |
添加单个元素 | 是 |
update(iterable) |
批量添加元素 | 是 |
remove(x) |
删除元素,不存在抛 KeyError |
是 |
discard(x) |
删除元素,不存在不报错 | 是 |
pop() |
随机弹出并返回一个元素 | 是 |
clear() |
清空集合 | 是 |
union(other) |
并集 | 否 |
intersection(other) |
交集 | 否 |
difference(other) |
差集 | 否 |
symmetric_difference(other) |
对称差集 | 否 |
issubset(other) |
是否为子集 | 否 |
issuperset(other) |
是否为超集 | 否 |
isdisjoint(other) |
是否无交集 | 否 |
copy() |
浅拷贝 | 否 |
6. 使用注意事项
set无序,不能通过下标访问 ,需要索引时先转成list并排序。set元素必须可哈希,list、dict、set不能直接放入;如需存放,可转成tuple或frozenset。- 需要不可变集合时使用
frozenset,它可以作为字典的键或另一个集合的元素。 - 判断成员是否存在时优先用
set而不是list,数据量大时性能差距非常明显。
python
# frozenset 示例
fs = frozenset([1, 2, 3])
print(fs) # frozenset({1, 2, 3})
print({fs: "value"}) # frozenset 可作为字典键
7. 总结
set 是 Python 中处理去重、成员判断、集合运算 的利器。掌握 add、update、remove、discard 等增删方法,以及 union、intersection、difference 等运算方法,再结合本文的实战案例,基本可以覆盖日常开发中的绝大多数场景。