在进行字典更新时, 我们通常都是用update函数, 但这个函数只能更新第一层, 如果第2/3/...层也需要更新的, 就不能再用update了, 否则从第2层起都会被覆盖;
由于暂时没有找到合适的方法, 就自己写了一个函数, 来进行字典的深度更新, 可以代替update, 能够满足浅层和深层的更新.
1. 问题描述
先定义两个字典:
dict_1 = {"A": 1, "B": {"b1": 1, "b2": 2}}
dict_2 = {"B": {"b2": 22, "b3": 3, "b4": {"bb1": 1}}, "C": 3}
我们想要达到的目的是: 使用dict_2来更新dict_1, 将dict_2中有而dict_1没有的key更新到dict_1, 同时将其共有的key更新为dict_2中的内容;
按照这个要求, 我们期望的结果应该是:
{'A': 1, 'B': {'b1': 1, 'b2': 22, 'b3': 3, 'b4': {'bb1': 1}}, 'C': 3}
如果我们直接用自带的update来更新, 效果是这样的:
dict_1.update(dict_2)
print(dict_1)
# result: {'A': 1, 'B': {'b2': 22, 'b3': 3, 'b4': {'bb1': 1}}, 'C': 3}
可见, update会直接把第一层的value直接覆盖过去, 对于dict_1['B']直接替换为了dict_2['B'], 导致dict_1['B']['b1']丢失; 这显然不是我们想要的结果.
2. 解决方案
解决的思路很简单, 分两步:
对于原dict有而新dict没有的key, 递归进行赋值;
对于新dict有而原dict没有的key, 添加到原dict中;
代码实现如下:
def dict_update(raw, new):
dict_update_iter(raw, new)
dict_add(raw, new)
def dict_update_iter(raw, new):
for key in raw:
if key not in new.keys():
continue
if isinstance(raw[key], dict) and isinstance(new[key], dict):
dict_update(raw[key], new[key])
else:
raw[key] = new[key]
def dict_add(raw, new):
update_dict = {}
for key in new:
if key not in raw.keys():
update_dict[key] = new[key]
raw.update(update_dict)
if __name__ == '__main__':
dict_1 = {"A": 1, "B": {"b1": 1, "b2": 2}}
dict_2 = {"B": {"b2": 22, "b3": 3, "b4": {"bb1": 1}}, "C": 3}
# dict_1.update(dict_2)
dict_update(dict_1, dict_2)
print(dict_1)
使用了dict_update函数, dict_1的内容就成了:
{'A': 1, 'B': {'b1': 1, 'b2': 22, 'b3': 3, 'b4': {'bb1': 1}}, 'C': 3}
目标达成!