集合(set)在 Python 中存放不重复且可哈希的元素,本身无序。典型用途包括序列去重,以及并集、交集、差集与对称差等运算。本节说明创建方式、增删成员、遍历与成员检测,并介绍运算符与对应方法。元素须可哈希,列表与字典不能直接作为集合元素。
集合长什么样
非空集合可用花括号字面量表示。打印时元素顺序可能与书写顺序不一致,这是无序类型的正常表现:
s = {1, 2, 3}
print(s) # {1, 2, 3}
print(type(s)) # <class 'set'>自动去重
重复加入同一值时,集合中仅保留一份。将列表转为 set 再转回 list 是常用的去重方式,但转回列表后的顺序未必与原列表一致。若须保持首次出现顺序,需另行实现:
s = {1, 2, 2, 3, 3, 3}
print(s) # {1, 2, 3}
nums = [1, 2, 2, 3, 3, 3, 4]
unique = list(set(nums))
print(unique) # [1, 2, 3, 4] 次序可能不同创建集合
由可迭代对象构造时使用 set(...),字符串会按字符拆分再去重。空集合只能写作 set():在 Python 中,{} 表示空字典,与非空集合的花括号字面量容易混淆:
a = {1, 2, 3}
b = set()
c = set("hello")
print(c) # {'h', 'e', 'l', 'o'}
empty = {}
print(type(empty)) # <class 'dict'>
empty2 = set()
print(type(empty2)) # <class 'set'>添加与删除
add 加入单个元素。discard 与 remove 均可删除元素,区别在于目标不存在时前者静默忽略,后者抛出 KeyError。pop 移除并返回某一元素,具体哪一个未定义,因此不宜依赖弹出顺序。clear 清空集合:
s = {1, 2, 3}
s.add(4)
s.discard(2)
s.remove(1)
s.pop()
print(s)
s.clear()遍历集合
for 可遍历当前全部元素,但迭代顺序在不同运行间可能不同。成员检测使用 in,平均时间复杂度较低,适合判断元素是否出现过:
s = {"apple", "banana", "cherry"}
for x in s:
print(x, end=" ")
print()
print("apple" in s) # True集合运算
两个集合之间既可用运算符,也可调用同名方法,结果等价。并集包含两侧全部元素,交集为公共部分,差集为仅在左操作数中的元素,对称差为去掉交集后两侧的剩余元素:
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
print(a | b) # 并集
print(a.union(b))
print(a & b) # 交集
print(a.intersection(b))
print(a - b) # 差集:在 a 不在 b
print(a.difference(b))
print(a ^ b) # 对称差
print(a.symmetric_difference(b))
上述运算通常返回新集合,不修改原操作数。若须原地更新,可使用 update、intersection_update 等方法。
集合关系判断
除生成新集合外,还可判断子集、超集及是否无交集:
a = {1, 2, 3}
b = {1, 2}
print(b.issubset(a)) # True
print(a.issuperset(b)) # True
print(a.isdisjoint({7})) # True,没有交集常见误区
- 空集合须写
set(),{}表示空字典。 {[1, 2]}因列表不可哈希将触发TypeError。- 遍历顺序不稳定,业务逻辑不应依赖第几个元素。
本节说明了 Python 集合的创建、去重与集合运算。下一篇介绍字典:键到值的映射及增删改查。