Короткий ответ
Словари объединяют через метод dict.update(), распаковку {d1, d2} или оператор | (Python 3.9+); во всех способах при совпадении ключей выигрывает значение из словаря, указанного позже (правее / последним применённым).
Как это работает подробнее
d1.update(d2) изменяет d1 на месте, перезаписывая совпадающие ключи значениями из d2. {d1, d2} и d1 | d2 создают новый словарь, не изменяя исходные; порядок распаковки или операндов определяет, чьё значение "побеждает" при одинаковых ключах — побеждает тот, что применён позже.
Пример кода
example.py
defaults = {"timeout": 30, "retries": 3}
overrides = {"retries": 5, "debug": True}
merged = {**defaults, **overrides}
print(merged) # {'timeout': 30, 'retries': 5, 'debug': True}
merged2 = defaults | overrides
print(merged2 == merged) # True, тот же результат другим синтаксисом
defaults.update(overrides) # изменяет defaults на месте, возвращает None
print(defaults) # {'timeout': 30, 'retries': 5, 'debug': True}Что использовать на практике
- Практика. Если нужно сохранить оба исходных словаря без изменений — используют
|или распаковку. Если исходный словарь можно мутировать и важна скорость для большого числа обновлений —update()эффективнее, так как не создаёт новый объект. Начиная с 3.9 есть также|=для обновления на месте в стиле, похожем наupdate.
Подводные камни
- Риски. Думают, что
update()возвращает новый словарь — метод возвращаетNone, результат нужно смотреть в изменённом исходном объекте. Также не учитывают порядок операндов в|/распаковке и получают не то значение при пересекающихся ключах.