Questa domanda è vecchia, ma sono atterrato qui durante la ricerca di una soluzione di "fusione profonda". Le risposte sopra hanno ispirato ciò che segue. Ho finito per scrivere il mio perché c'erano bug in tutte le versioni che ho testato. Il punto critico mancato è stato, a una profondità arbitraria dei due dicts di input, per qualche chiave, k, l'albero decisionale quando d [k] o u [k] non è un dict era difettoso.
Inoltre, questa soluzione non richiede ricorsione, che è più simmetrica rispetto a come dict.update()
funziona e restituisce 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))