用 defaultdict(list) 可避免键重复时值被覆盖,自动将同键值收集为列表;还可通过更换 default_factory 实现累加、去重等聚合逻辑,比 setdefault 更高效清晰。

合并多个字典时遇到重复键,值被覆盖怎么办
直接用 dict.update() 或 {**d1, **d2} 合并多个字典,相同键的值会后覆盖前——这不是“合并”,是“丢数据”。真正需要的是把同键的值收集起来,比如变成列表、求和或去重。collections.defaultdict 正是为此设计:它能自动为不存在的键初始化默认容器,省去手动判断 if key not in d 的麻烦。
用 defaultdict(list) 收集所有同键的值
这是最常见需求:把多个字典中同一键对应的值全部保留下来,不丢失任何信息。
实操建议:
- 初始化
defaultdict(list),然后遍历每个字典,对每个key, value执行merged[key].append(value) - 注意:如果原始字典的值本身是可变对象(如列表、字典),
append()存的是引用;需深拷贝时用copy.deepcopy(value) - 最后若需普通字典,调用
dict(merged)即可
from collections import defaultdict
d1 = {'a': 1, 'b': 2}
d2 = {'a': 3, 'c': 4}
d3 = {'b': 5, 'a': 6}
<p>merged = defaultdict(list)
for d in [d1, d2, d3]:
for k, v in d.items():
merged[k].append(v)</p><h1>结果:{'a': [1, 3, 6], 'b': [2, 5], 'c': [4]}</h1>
换 default_factory 实现不同聚合逻辑
defaultdict 的威力不在“默认为 list”,而在你能指定任意可调用对象作为工厂函数。值类型决定后续怎么处理数据。
常见组合:
-
defaultdict(int)→ 累加数值:merged[key] += value -
defaultdict(set)→ 去重合并:merged[key].add(value) -
defaultdict(lambda: 0.0)→ 初始化浮点数累加器 -
defaultdict(list)+ 后续sum()或max()→ 灵活二次计算
别硬套 int 处理字符串;也别用 set 存无法哈希的对象(如字典、列表)——会报 TypeError: unhashable type。
和 dict.setdefault() 对比:什么情况下该选 defaultdict
单次合并几个小字典,dict.setdefault(key, []).append(value) 也能工作。但 defaultdict 更清晰、更少出错。
关键区别:
-
setdefault每次都执行一次函数调用(哪怕键已存在),而defaultdict只在键缺失时调用工厂函数 - 嵌套结构(如
defaultdict(lambda: defaultdict(list)))用setdefault写起来极其冗长且易错 - 如果合并逻辑复杂(比如按类型分组、带条件过滤),
defaultdict的初始化语义更利于拆解和测试
真正容易被忽略的是:defaultdict 返回的对象仍是 dict 子类,但打印或 JSON 序列化时会暴露其类型——调试时看到 defaultdict(<class>, {...})</class> 别慌,转成 dict 就正常了。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











