Cette question est ancienne, mais j'ai atterri ici en cherchant une solution de "fusion profonde". Les réponses ci-dessus ont inspiré ce qui suit. J'ai fini par écrire le mien car il y avait des bugs dans toutes les versions que j'ai testées. Le point critique manqué était, à une certaine profondeur arbitraire des deux dicts d'entrée, pour une clé, k, l'arbre de décision lorsque d [k] ou u [k] n'est pas un dict était défectueux.
En outre, cette solution ne nécessite pas de récursivité, qui est plus symétrique avec la façon dont dict.update()
fonctionne et retourne None
.
import collections
def deep_merge(d, u):
"""Do a deep merge of one dict into another.
This will update d with values in u, but will not delete keys in d
not found in u at some arbitrary depth of d. That is, u is deeply
merged into d.
Args -
d, u: dicts
Note: this is destructive to d, but not u.
Returns: None
"""
stack = [(d,u)]
while stack:
d,u = stack.pop(0)
for k,v in u.items():
if not isinstance(v, collections.Mapping):
# u[k] is not a dict, nothing to merge, so just set it,
# regardless if d[k] *was* a dict
d[k] = v
else:
# note: u[k] is a dict
# get d[k], defaulting to a dict, if it doesn't previously
# exist
dv = d.setdefault(k, {})
if not isinstance(dv, collections.Mapping):
# d[k] is not a dict, so just set it to u[k],
# overriding whatever it was
d[k] = v
else:
# both d[k] and u[k] are dicts, push them on the stack
# to merge
stack.append((dv, v))