Этот вопрос старый, но я попал сюда при поиске решения "глубокого слияния".Ответы выше вдохновили то, что следует.Я написал свою собственную, потому что во всех версиях, которые я тестировал, были ошибки.Пропущенная критическая точка была, на некоторой произвольной глубине двух входных диктов, для некоторого ключа, k, деревом решений, когда d [k] или u [k] равно не адикт был ошибочным.
Кроме того, это решение не требует рекурсии, которое более симметрично с тем, как работает dict.update()
, и возвращает 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))