Python集合去重靠哈希表实现,平均时间复杂度O(1)每次插入,整体O(n);依赖对象可哈希性,不可变类型如int/str/tuple可入set,list/dict/set则不可;保序去重推荐dict.fromkeys(),浮点精度、自定义类未重写__hash__和__eq__、字符串未归一化是三大易错点。
Python 集合去重靠的是哈希表(hash table)底层实现,不是遍历比对。这意味着 set 去重平均时间复杂度是 O(1) 每次插入,整体 O(n),远快于用 list 手动查重的 O(n²)。
set 能秒级去重?因为 set 内部用哈希表存储元素:每个元素先算 hash(),映射到固定桶位;冲突时用开放寻址或链地址法处理。只要对象可哈希(immutable 且实现 __hash__ 和 __eq__),就能进 set。
int、str、tuple(不含可变项)、frozenset
list、dict、set —— 直接加会报 TypeError: unhashable type
hash() 值相同且 __eq__ 返回 True 的对象,会被视为重复项别无脑转 list(set(...)) —— 它不保序,还可能出错。
dict.fromkeys(items) 最快最安全,Python 3.7+ 保证插入顺序dict 当“有序集合”容器
list)要去重:tuple(item)(仅当 item 是一维 list 且元素可哈希)frozenset 处理无序集合型数据set 边读边判重:seen = set()
unique_items = []
for item in large_iterable:
if item not in seen:
seen.add(item)
unique_items.append(item)set 去重的三个易踩坑点这些错误不会报错,但结果不对,调试起来很隐蔽。
0.1 + 0.2 != 0.3,进 set 可能被当成不同元素__hash__ 和 __eq__:默认按内存地址哈希,两个值相同的实例仍算不同"abc " 和 "abc" 是两个不同 str,set 不会自动 strip 或 lower真正难的不是“怎么去重”,而是想清楚“什么才算重复”——哈希只认字面值相等,不理解业务语义。比如日期字符串 "2025-01-01" 和 datetime.date(2025, 1, 1),在 set 里永远不重复,哪怕你心里觉得它们代表同一天。