set()去重最快但丢序且不支持不可哈希类型;保序推荐dict.fromkeys(lst).keys()转list;含字典时需用业务键或json.dumps()预处理;大数据量应流式处理。

用 set() 去重最简单,但会丢顺序、不支持不可哈希类型
Python 里最常用的去重方式就是 list(set(lst)),快且短。但它只适合元素全是 int、str、tuple 这类可哈希类型的列表,一旦含 dict 或 list 就直接报 TypeError: unhashable type: 'dict'。另外,set 不保留原始顺序——哪怕你用的是 Python 3.7+,set 本身不保证插入序,list(set(...)) 的结果顺序是不确定的。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 仅用于临时去重、且确定元素全可哈希、顺序无关的场景(比如统计唯一标签)
- 别在生产逻辑里依赖它的输出顺序
- 想保序又简单?改用
dict.fromkeys(lst).keys(),它利用字典键的唯一性和插入序(Python 3.7+),比set多半步但更可控
dict.fromkeys() 是保序去重的默认选择,但要注意返回视图对象
dict.fromkeys(lst) 返回一个字典,键是去重后的元素,值全为 None;取 .keys() 得到的是一个 dict_keys 视图——它不是列表,不能索引、不能切片,直接传给需要 list 的函数(比如 numpy.array())会出错。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 要列表就显式转:
list(dict.fromkeys(lst)) - 如果原列表超大(千万级),这个操作内存开销接近原列表两倍(字典 + 新列表),不如流式处理
- 对嵌套结构无效:
dict.fromkeys([{"a":1}, {"a":1}])仍会报错,因为dict不可哈希
含字典或自定义对象时,得靠 json.dumps() 或自定义 key 函数
遇到 [{"id":1}, {"id":1}, {"id":2}] 这种,必须把“相等逻辑”显式写出来。常见做法是用 json.dumps(item, sort_keys=True) 当临时哈希键,但要注意:float 精度、NaN、顺序敏感字段(如时间戳字符串)、不含 datetime 等非 JSON 类型都会崩。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 优先用业务主键:比如每个字典都有
"id",那就用seen = set(); [x for x in lst if x["id"] not in seen and not seen.add(x["id"])] - 真要序列化比较,加
default=str防止TypeError,并提前sort_keys=True统一结构 - 别在循环里反复调
json.dumps(),性能差;先预处理成 key 列表再去重
大数据量或需流式处理时,别一次性加载,用生成器 + 缓存集合
当列表有百万行以上,或来自文件/数据库游标,list(dict.fromkeys(...)) 会吃光内存。这时候得边读边判重,用一个 set 记已见 key,配合生成器 yield 结果。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 核心模式:
seen = set(); for item in iterable: key = get_key(item); if key not in seen: seen.add(key); yield item -
get_key()必须稳定、轻量,避免在里头做json.dumps()或复杂计算 - 如果 key 可能超多(比如用户 ID 十亿级),
set内存占用大,考虑用bloom filter(牺牲少量准确率换内存)或分块处理










