dict.fromkeys()是python 3.7+最简安全的顺序去重方案,适用于可哈希对象;对不可哈希对象需用json.dumps(sort_keys=true)或自定义__hash__和__eq__方法。

用 dict.fromkeys() 保持顺序去重(Python 3.7+)
Python 3.7+ 中,dict 保证插入顺序,所以 dict.fromkeys() 是最简、最安全的方案——它天然去重且不打乱顺序,比手写循环或 set 配合遍历更可靠。
- 只适用于对象可哈希(如
tuple、str、int),但复杂对象(如dict、自定义类实例)默认不可哈希 - 若列表里是字典,需先转成可哈希形式,例如
tuple(sorted(d.items()));注意:这会丢失原始键序(Python 3.7+ 字典本身有序,但sorted()会按字母序重排) - 示例:对元组列表去重:
list(dict.fromkeys([(1,2), (3,4), (1,2)]))→[(1,2), (3,4)]
对不可哈希对象(如 dict 列表)用 json.dumps() + set 辅助去重
当列表元素是字典、嵌套结构等不可哈希类型时,靠序列化为字符串再判重是常见折中做法。关键点不是“能不能”,而是“怎么序列化才不误判”。
- 必须加
sort_keys=True,否则{"a":1,"b":2}和{"b":2,"a":1}序列化结果不同,会被当成两个不同项 - 浮点数精度、
None/None与None的一致性通常没问题,但含datetime、Decimal等需自定义default参数,否则报TypeError - 性能上,每项都做
dumps+ 字符串比较,大数据量时明显慢于哈希方案 - 示例:
import json seen = set() unique = [] for item in dict_list: key = json.dumps(item, sort_keys=True) if key not in seen: seen.add(key) unique.append(item)
自定义类对象去重:必须实现 __hash__ 和 __eq__
如果列表里是自定义类实例,仅靠 dict.fromkeys() 会失败(抛 TypeError: unhashable type),根本原因是 Python 不知道“两个实例何时算相同”。
- 必须同时实现
__eq__(定义相等逻辑)和__hash__(返回稳定整数),且满足:相等的对象必须有相同hash - 若只重写
__eq__不写__hash__,实例会自动变为不可哈希(__hash__ = None) - 常见错误:用
id(self)当hash值——这会让所有实例都被视为不同,完全失去去重意义 - 推荐写法:
__hash__基于参与相等判断的字段计算,例如return hash((self.name, self.age))
为什么不用 set() 直接去重?
直接写 list(set(my_list)) 在绝大多数场景下都错:不仅顺序全乱,还会在不可哈希对象时报错,而且没有提示。
-
set构造本身无序,Python 不保证其内部迭代顺序(即使当前 CPython 实现看起来“有时像原序”,也不应依赖) - 一旦列表含不可哈希项(如字典),立刻抛
TypeError: unhashable type: 'dict',而这个错误容易被忽略成“数据有问题”,而非“方法用错了” - 哪怕你用
set辅助去重(如记录已见 key),也必须配合外部列表收集,不能省略顺序维护逻辑
json.dumps(sort_keys=True) 的配合——不加 sort_keys=True,看似能跑通,但会在某些数据上漏去重;而自定义类忘记同步实现 __hash__,则会让 dict.fromkeys() 完全失效,且错误信息不直观。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











