人人都会AI编程

集合类型:set、frozenset

更新时间:2026-07-12

集合(set)是 Python 中专门用于存储不重复、无序元素的数据结构,基于哈希表实现。它和我们数学中“集合”的概念很相似,支持交集、并集、差集等运算。frozenset 是集合的不可变版本。

set:可变集合

创建方式

# 直接使用花括号
s = {1, 2, 3, 3, 2}   # 自动去重 → {1, 2, 3}

# 使用 set() 函数(从可迭代对象构造)
s = set([1, 2, 3, 2])  # {1, 2, 3}
s = set("hello")       # {'h', 'e', 'l', 'o'}

核心特性

  • 无序性:元素的存储顺序由哈希值决定,与插入顺序无关(不要依赖顺序)。
  • 元素唯一:自动去重,同一个值只会保留一个。
  • 元素必须可哈希:只有不可变类型(如数字、字符串、元组)能放入集合,列表、字典这些可变对象不行。

常用操作

s = {1, 2, 3}
s.add(4)                 # 添加单个元素
s.remove(2)              # 移除指定元素,不存在会报错
s.discard(5)             # 安全移除,不存在也不报错
s.pop()                  # 随机弹出一个元素(不确定是哪个)

集合运算

a = {1, 2, 3}
b = {2, 3, 4}
a & b        # 交集 → {2, 3}       也可以用 a.intersection(b)
a | b        # 并集 → {1, 2, 3, 4}  a.union(b)
a - b        # 差集(在a不在b)→ {1} a.difference(b)
a ^ b        # 对称差集(只出现在一边)→ {1, 4} a.symmetric_difference(b)

实际使用场景

  • 快速去重:对一个大列表去重,list(set(my_list)) 比手写循环快得多。
  • 成员判断:对大量数据的“是否存在”检查,集合的 O(1) 查找远快于列表的 O(n)。
  • 关系判断:检查一个列表是否包含另一个列表的所有元素时,转成集合做差集或子集判断。
  • 数学集合运算:如统计两个用户组的共同用户、差异用户。

frozenset:不可变集合

frozenset 与 set 行为几乎一样,只是创建后不可修改(不能 add、remove 等),因此它是可哈希的,可以作为字典的键,也可以放入另一个 set 中。

创建

fs = frozenset([1, 2, 3])   # frozenset({1, 2, 3})

为什么需要 frozenset

  • 当你需要一个“常量集合”,不希望被意外修改时。
  • 当你想用集合作为字典的键时(set 本身不可哈希,不能当键),比如:
  groups = {frozenset({'Alice', 'Bob'}): 'team_a'}
  
  • 实际上,在装饰器、缓存等场景中,frozenset 的不可变性使其更安全。

与 set 的简单对比
| 特性 | set | frozenset |
|------|-----|-----------|
| 可变性 | 可变,可增删 | 不可变,一旦创建不能修改 |
| 可哈希 | 否(不能作为字典键) | 是(可以作为字典键) |
| 适用场景 | 普通集合操作 | 常量化集合、嵌套或当键 |

注意事项

  • 集合虽然本身是无序的,但 Python 3.7 以上保留插入顺序?不,字典才保留插入顺序,集合没有这个保证,不要依赖顺序。
  • 创建空集合只能用 set(),不能用 {}(因为 {} 是空字典)。
  • 集合操作多数有对应的运算符版本|, &, -, ^),也有等价的方法名union, intersection 等),方法可以接受任意可迭代对象,运算符两边则必须是集合。

集合和 frozenset 是处理“唯一性”需求最直接有力的工具,尤其在数据去重、快速查找和关系运算中,远比列表高效和语义清晰。