Python集合核心是无序、唯一、可变(元素须不可变),底层哈希表实现,查增删平均O(1);因要求元素可哈希,故列表字典等可变类型不可作为元素。

Python集合(set)的核心原理其实就三点:无序、唯一、可变(但元素必须不可变)。它底层用哈希表实现,所以查、增、删都是平均 O(1) 时间复杂度——这点比列表快得多,也是它最值得用的地方。
为什么集合不能存列表或字典?
因为集合要求所有元素“可哈希”(hashable),即对象创建后内存地址和哈希值不变。列表、字典是可变类型,随时可能被修改,哈希值会变,破坏哈希表结构。常见可哈希类型有:int、str、tuple(且内部元素也都可哈希)、frozenset;不可哈希的有:list、dict、set、bytearray。
例如:
- ✅ {1, "hello", (2, 3)} —— 合法,tuple 内部没可变项
- ❌ {1, [2, 3]} —— 报错 TypeError: unhashable type: 'list'
- ✅ {1, frozenset([2, 3])} —— frozenset 是不可变集合,可作元素
集合运算的实战技巧
别总用 for 循环去“去重”或“找共同项”,直接用内置方法或运算符更简洁、更快。
立即学习“Python免费学习笔记(深入)”;
-
去重并保持顺序?用
dict.fromkeys(iterable)转 list,或 Python 3.7+ 可用list(dict.fromkeys(lst));纯 set 会丢顺序。 -
找两组数据的交集/差集/并集?
•a & b或a.intersection(b)→ 共同元素
•a - b或a.difference(b)→ a 有 b 没有的
•a ^ b或a.symmetric_difference(b)→ 仅在其中一个里出现的 -
判断子集/超集?用
a.issubset(b)或a ;a.issuperset(b)或a >= b。
常见易错点与优化建议
很多同学写集合操作时踩坑,不是语法错,而是逻辑误判。
-
用
in判断成员比用list.index()或list.count()快一个数量级——尤其数据量大时,优先转 set 再查。 -
避免反复创建集合:比如循环里写
if x in [1,2,3,4,5],应提前定义valid_set = {1,2,3,4,5}。 -
更新集合别用
+=:它只对 list 有效;set 要用.update()(批量加)或.add()(单个加)。 -
frozenset 是唯一能当 dict 键的集合类型,适合做“组合键”,比如
cache[(frozenset(keys), mode)] = result。
一个小而实用的案例:日志去重分析
假设你有一批用户行为日志,每行是“用户ID 操作类型 时间戳”,想快速统计:今天执行过“login”也执行过“pay”的用户数。
- 读取日志,按用户ID分组,分别收集其操作类型 → 每个用户对应一个 set
- 筛选出同时含 'login' 和 'pay' 的用户集合:
login_users & pay_users - 比用嵌套循环或双重 if 判断快 5–10 倍,代码还少一半
理解哈希机制、掌握运算符语义、避开可变性陷阱,集合就能从“只会去重”变成高效数据协调工具。










