Python:如何优雅更新子字典?实现通用字典合并避免覆盖
嘿,这个问题我之前处理嵌套字典的时候也踩过坑!a.update(b)确实会直接覆盖相同键的内容,完全没法满足深层合并的需求。下面给你几种适配不同场景的方法,不管是简单字典还是复杂的嵌套字典都能搞定:
方法1:浅合并(适用于无嵌套的简单字典)
如果你的字典没有嵌套结构,只是需要把多个字典的键值对合并,重复键用后一个字典的值覆盖前一个,那么用字典解包语法或者Python 3.9+新增的|运算符最简洁高效:
# 字典解包(兼容Python 3.5+) dict_a = {"A": 1, "B": {"B1": 2}} dict_b = {"B": {"B2": 3}, "C": 4} merged_dict = {**dict_a, **dict_b} # 结果:{'A': 1, 'B': {'B2': 3}, 'C': 4} # Python 3.9+ 可用 | 运算符 merged_dict = dict_a | dict_b
这种方式会生成一个新字典,不会修改原有的dict_a或dict_b,比循环逐个处理效率高很多。如果要合并多个字典,可以结合functools.reduce:
from functools import reduce dict_list = [dict_a, dict_b, dict_c] merged_dict = reduce(lambda x, y: {**x, **y}, dict_list)
方法2:深层合并(支持嵌套字典,不直接替换子字典)
如果你的字典有嵌套结构,希望相同键的子字典也能合并而不是被直接替换,那就需要写一个递归的深层合并函数:
def deep_merge(original, update): # 先复制原字典,避免修改原数据 merged = original.copy() for key, value in update.items(): # 如果两边都是字典,递归合并子字典 if isinstance(value, dict) and key in merged and isinstance(merged[key], dict): merged[key] = deep_merge(merged[key], value) else: # 否则直接用update的值覆盖(或新增键) merged[key] = value return merged # 测试示例 dict_a = {"A": 1, "B": {"B1": 2}} dict_b = {"B": {"B2": 3}, "C": 4} merged_dict = deep_merge(dict_a, dict_b) # 结果:{'A': 1, 'B': {'B1': 2, 'B2': 3}, 'C': 4}
要合并多个嵌套字典,同样可以用reduce批量处理:
from functools import reduce dict_list = [dict_a, dict_b, dict_c] merged_dict = reduce(deep_merge, dict_list)
这种方法完全原生,不需要依赖第三方库,而且效率比循环逐个处理每个键值对高得多。
方法3:保留重复键的多值合并(可选)
如果你的需求不是覆盖重复键,而是把相同键的所有值都保留(比如合并成列表),可以用这个自定义函数:
def merge_with_duplicates(original, update): merged = original.copy() for key, value in update.items(): if key in merged: # 如果原键的值不是列表,先转成列表 if not isinstance(merged[key], list): merged[key] = [merged[key]] merged[key].append(value) else: merged[key] = value return merged # 测试示例 dict_a = {"A": 1, "B": 2} dict_b = {"B": 3, "C": 4} merged_dict = merge_with_duplicates(dict_a, dict_b) # 结果:{'A': 1, 'B': [2, 3], 'C': 4}
总结
- 简单无嵌套字典:用
{**a, **b}或a | b(3.9+),简洁高效; - 嵌套字典:用自定义递归
deep_merge函数,实现深层合并; - 需要保留重复键值:用
merge_with_duplicates函数。
这些方法都能一次性合并多个字典,比循环逐个处理单条键值对的效率高很多,完全适配你的需求。
内容的提问来源于stack exchange,提问作者Frostie
相关产品推荐
相关产品推荐

