
Сложение словарей – частая операция при работе с данными, конфигурациями и параметрами функций. Python предлагает несколько подходов, отличающихся синтаксисом, поведением при совпадении ключей и поддержкой в разных версиях языка.
Начиная с Python 3.9, появился оператор |, который объединяет два словаря, создавая новый. При этом значения из правого словаря замещают значения с совпадающими ключами из левого. Для получения обновлённого словаря на месте используется оператор |=.
В более ранних версиях (Python 3.5 и выше) для объединения можно использовать распаковку: {dict1, dict2}. Это работает аналогично оператору |, но требует создания нового словаря и не поддерживает обновление на месте.
Метод update() позволяет изменить существующий словарь, добавив в него пары из другого. Этот способ не возвращает результат, а вносит изменения непосредственно в объект, что важно учитывать при работе с копиями и ссылками.
Для специфических задач можно использовать collections.ChainMap, если важно сохранить доступ к оригинальным словарям без их объединения. Такой объект действует как объединённое отображение, но не копирует данные и не изменяет исходные структуры.
Выбор метода зависит от версии Python, необходимости сохранить оригинальные словари и требований к производительности. При объединении больших структур важно учитывать, что update() и операторы |/|= работают быстрее, чем распаковка, особенно при частом использовании в цикле.
Объединение словарей через оператор

Оператор позволяет создать новый словарь на основе распаковки других. При совпадении ключей сохраняется значение из словаря, расположенного правее.
Синтаксис:
dict3 = {dict1, dict2}
Пример:
dict1 = {'a': 1, 'b': 2}
dict2 = {'b': 3, 'c': 4}
result = {dict1, dict2}
# result = {'a': 1, 'b': 3, 'c': 4}
Ключ 'b' был перезаписан значением из dict2. Это поведение нужно учитывать при объединении, если важен порядок и сохранение данных.
Поддерживается с Python 3.5. До этой версии использование вызовет ошибку синтаксиса. Для более старых версий следует использовать метод update() или collections.ChainMap.
Допускается объединение более двух словарей:
combined = {dict1, dict2, dict3}
Можно комбинировать с добавлением новых пар:
new_dict = {dict1, 'd': 5}
Недопустимо использовать с несловарными типами, например:
{[('a', 1)]} # TypeError
Для объединения вложенных словарей требуется дополнительная логика. Простая распаковка не производит глубокое копирование и не объединяет подсловарей.
Использование метода dict.update() для изменения словаря на месте

Метод dict.update() позволяет изменить содержимое словаря без создания нового объекта. Он принимает либо другой словарь, либо итерируемый объект с парами ключ–значение, либо именованные аргументы.
Если ключ уже существует, его значение будет перезаписано. Если ключа нет, он будет добавлен. Типичный пример:
data = {'a': 1, 'b': 2}
extra = {'b': 3, 'c': 4}
data.update(extra)
# data: {'a': 1, 'b': 3, 'c': 4}
Передача аргументов напрямую:
data.update(d=5, e=6)
# data: {'a': 1, 'b': 3, 'c': 4, 'd': 5, 'e': 6}
Если передаётся итерируемый объект, каждый его элемент должен быть двухэлементной структурой:
pairs = [('f', 7), ('g', 8)]
data.update(pairs)
# data: {'a': 1, 'b': 3, 'c': 4, 'd': 5, 'e': 6, 'f': 7, 'g': 8}
Метод не возвращает новый словарь. Он возвращает None и изменяет словарь на месте. Это следует учитывать при попытке присваивания результата вызова update():
result = data.update({'h': 9})
# result: None, data: обновлён
Вложенные словари не объединяются рекурсивно. Внутренние структуры полностью заменяются:
nested = {'config': {'theme': 'dark'}}
nested.update({'config': {'layout': 'grid'}})
# nested: {'config': {'layout': 'grid'}}
Для объединения вложенных словарей требуется ручная обработка или рекурсивное слияние.
Создание нового словаря с помощью {d1, d2}
Конструкция {d1, d2} позволяет объединить два словаря в новый, не изменяя исходные. Работает начиная с Python 3.5. При конфликте ключей приоритет получает второй словарь: {{'a': 1}, {'a': 2}} даст {'a': 2}.
Синтаксис использует распаковку словарей: оператор разворачивает пары ключ–значение внутрь нового литерала словаря. Это эквивалентно передаче аргументов с ключами при вызове функции, но используется для создания новых структур данных.
Метод подходит для случаев, когда требуется сохранить исходные словари без изменений. Также его удобно использовать в выражениях внутри функций и генераторов, например: func({defaults, overrides}).
Если один из операндов пустой, результат – копия второго. Если оба пустые, результат – пустой словарь. Допустимо объединять более двух словарей: {d1, d2, d3}.
Тип значений не влияет на поведение: конфликт определяется только по ключам. Значения не объединяются, а перезаписываются. Чтобы избежать потери данных при повторении ключей, предварительно анализируй пересечения: set(d1) & set(d2).
Способ работает только с объектами типа dict. Попытка использовать {some_mapping} с collections.defaultdict или collections.OrderedDict приведёт к приведению к обычному словарю и потере специфического поведения.
Объединение словарей с учётом повторяющихся ключей

Если при объединении словарей требуется сохранить все значения по повторяющимся ключам, можно использовать collections.defaultdict с типом значений list.
Пример:
from collections import defaultdict
d1 = {'a': 1, 'b': 2}
d2 = {'a': 3, 'c': 4}
result = defaultdict(list)
for d in (d1, d2):
for key, value in d.items():
result[key].append(value)
print(dict(result))
# {'a': [1, 3], 'b': [2], 'c': [4]}
Если значения не нужно группировать в списки, а требуется, например, суммировать их, логика меняется:
from collections import Counter
d1 = {'a': 2, 'b': 3}
d2 = {'a': 4, 'b': 1, 'c': 5}
merged = dict(Counter(d1) + Counter(d2))
print(merged)
# {'a': 6, 'b': 4, 'c': 5}
Для произвольной логики объединения лучше использовать functools.reduce и функцию, обрабатывающую пары ключ-значение:
from functools import reduce
dicts = [{'a': 1}, {'a': 2, 'b': 3}, {'a': 5, 'b': 1}]
def merge(a, b):
result = a.copy()
for k, v in b.items():
result[k] = result.get(k, 0) + v
return result
result = reduce(merge, dicts)
print(result)
# {'a': 8, 'b': 4}
Объединение с учётом значений полезно при агрегации данных. Поведение при повторяющихся ключах всегда должно быть определено явно: перезапись, сложение, сохранение всех вариантов или любая другая операция.
Сложение словарей через collections.Counter

Модуль collections содержит класс Counter, предназначенный для подсчёта элементов. Его можно использовать для сложения словарей, если значения – числовые.
Пример использования:
from collections import Counter
a = {'яблоки': 3, 'груши': 5}
b = {'груши': 2, 'апельсины': 4}
result = Counter(a) + Counter(b)
print(dict(result))
# {'яблоки': 3, 'груши': 7, 'апельсины': 4}
Особенности:
Counterскладывает значения одинаковых ключей.- Ключи с нулевыми или отрицательными значениями автоматически исключаются при преобразовании в словарь.
Подходит, если:
- нужна агрегация числовых данных;
- важно сохранить только положительные значения;
- не требуется поддержка вложенных структур или типов, отличных от чисел.
Не подходит, если:
- значения – строки, списки, bool;
- важно сохранить нули или отрицательные значения;
- нужна строгая типовая совместимость (Counter возвращает подкласс dict).
Рекомендация: перед использованием Counter для сложения словарей убедитесь, что все значения – числа. Иначе результат будет непредсказуем.
Применение ChainMap из модуля collections
ChainMap из модуля collections позволяет эффективно работать с несколькими словарями, объединяя их в один объект, при этом сохраняя их независимость. Это полезно, когда нужно работать с несколькими источниками данных, не изменяя их напрямую.
В отличие от простого объединения словарей, ChainMap позволяет использовать их в цепочке, и доступ к ключам осуществляется по принципу поиска по очереди. Если ключ есть в нескольких словарях, возвращается значение первого найденного, что позволяет избежать дублирования кода для обработки пересечений данных.
Пример создания ChainMap:
from collections import ChainMap
dict1 = {'a': 1, 'b': 2}
dict2 = {'b': 3, 'c': 4}
chain = ChainMap(dict1, dict2)
print(chain['b']) # Вернется 2, так как 'b' присутствует в dict1
print(chain['c']) # Вернется 4, так как 'c' есть только в dict2
Особенности использования:
- Изменение значений: изменение значений в ChainMap затрагивает только первый словарь в цепочке. Если его нет, изменения касаются следующих словарей.
- Добавление новых элементов: для добавления новых элементов используется метод
new_child(), который позволяет создавать новый словарь, добавляющийся в начало цепочки.
Пример добавления нового словаря в цепочку:
new_dict = {'d': 5}
chain = chain.new_child(new_dict)
print(chain['d']) # Вернется 5
Этот подход полезен в случаях, когда нужно динамически расширять список источников данных без риска изменения исходных словарей. Например, при обработке пользовательских данных или настройках, которые могут быть изменены в ходе выполнения программы.
Преимущества ChainMap:
- Минимизация дублирования данных и кода.
- Удобство в работе с несколькими словарями, например, для управления настройками приложения с приоритетами.
- Поддержка неизменяемости исходных данных при добавлении новых элементов.
Циклическое объединение словарей с пользовательской логикой

Циклическое объединение словарей позволяет комбинировать несколько словарей, в которых могут быть одинаковые ключи. Это объединение не просто перезаписывает значения, а использует определённую логику для их обработки. В Python такой подход можно реализовать с помощью пользовательской функции или lambda-выражения, учитывая особенности объединяемых данных.
Основной задачей в циклическом объединении является обработка конфликтующих ключей. Вместо того чтобы просто заменить одно значение другим, можно использовать, например, сумму, выбор максимального или минимального значения, объединение коллекций и другие операции.
Рассмотрим пример циклического объединения, где для одинаковых ключей будет суммироваться их значения. Мы будем использовать цикл и проверку существования ключа в результатирующем словаре.
def merge_dicts(dicts):
result = {}
for d in dicts:
for key, value in d.items():
if key in result:
result[key] += value # Проводим операцию суммирования
else:
result[key] = value
return result
В этом примере циклически обрабатываются все словари, и для каждого ключа выполняется операция суммирования значений. Это полезно в случаях, когда требуется аккумулировать данные из разных источников, например, при обработке статистики.
Также можно добавить пользовательскую логику для более сложных операций. Например, при объединении значений для одинаковых ключей можно выбирать максимальное значение:
def merge_dicts_max(dicts):
result = {}
for d in dicts:
for key, value in d.items():
if key in result:
result[key] = max(result[key], value) # Выбираем максимальное значение
else:
result[key] = value
return result
В этом случае для каждого ключа в результирующем словаре будет записано максимальное значение среди всех переданных словарей.
Если требуется более сложная логика, например, объединение коллекций, можно использовать следующую функцию:
def merge_dicts_union(dicts):
result = {}
for d in dicts:
for key, value in d.items():
if key in result:
result[key].update(value) # Объединение множества
else:
result[key] = value
return result
Здесь для каждого ключа объединяются множества (если значениями являются множества), что позволяет аккумулировать уникальные элементы из разных словарей.
Циклическое объединение с пользовательской логикой требует внимательности к типам данных и обеспечению корректности выполняемых операций. Выбор операции зависит от контекста задачи и типа значений в словарях.
Сравнение скорости разных способов объединения словарей

В Python существует несколько способов объединения словарей, и важно понимать их различия в плане производительности. Рассмотрим основные методы и их характеристики.
Первый способ – это использование оператора update(). Этот метод изменяет словарь на месте, добавляя или обновляя ключи из другого словаря. Он имеет время работы O(n), где n – это количество элементов в словаре, который добавляется. Однако стоит учитывать, что он не возвращает новый словарь, а изменяет существующий.
Второй способ – это использование оператора |, доступного в Python 3.9 и выше. Этот метод позволяет создать новый словарь, объединяя два других. Его время работы также O(n), но отличие от update() в том, что создается новый объект, не изменяя оригинальные словари. Это может быть полезно в случаях, когда требуется сохранить исходные данные.
Третий метод – использование распаковки словарей с помощью синтаксиса . Это позволяет объединить несколько словарей в один, передавая их как аргументы в функцию. Несмотря на свою универсальность, этот метод может быть медленнее по сравнению с другими, поскольку требует дополнительной обработки каждого словаря для распаковки. Время работы этого метода также O(n), но в реальных задачах его производительность может уступать предыдущим методам.
Тесты показали, что для объединения двух словарей с большим количеством элементов update() часто оказывается быстрее других методов, особенно если важно изменить один из словарей. В случае, когда необходима гарантия, что исходные словари не будут изменены, лучше использовать оператор |. Метод с распаковкой может быть полезен для более гибких решений, но его скорость будет уступать операторам update() и |.
Вопрос-ответ:
Какие способы сложения словарей в Python существуют?
В Python можно объединять словари несколькими способами. Одним из наиболее популярных методов является использование оператора `|`, который был введён в Python 3.9. Например, `dict1 | dict2` создаст новый словарь, который содержит элементы обоих словарей. Кроме того, можно воспользоваться методом `.update()`, который обновляет первый словарь элементами второго. Если нужно объединить несколько словарей в одном выражении, можно использовать конструкцию в стиле «распаковки» словарей, которая появилась в Python 3.5: `new_dict = {**dict1, **dict2}`. Этот метод также создаёт новый словарь, не изменяя исходные.
Как работает оператор `|` при сложении словарей?
Оператор `|` для словарей был введён в Python 3.9. Он позволяет объединять два или более словарей, создавая новый словарь. Если в словарях есть одинаковые ключи, то значения из второго словаря заменяют значения из первого. Например, если у нас есть два словаря: `dict1 = ‘a’: 1, ‘b’: 2}` и `dict2 = {‘b’: 3, ‘c’: 4}`, то при сложении их через `dict1 `, где значение для ключа `’b’` обновляется до 3.
Можно ли использовать метод `update()` для объединения нескольких словарей?
Метод `.update()` в Python используется для добавления элементов из одного словаря в другой. Однако стоит помнить, что этот метод изменяет словарь, к которому применяется. Например, если у вас есть два словаря: `dict1 = {‘a’: 1, ‘b’: 2}` и `dict2 = {‘b’: 3, ‘c’: 4}`, то вызов `dict1.update(dict2)` изменит `dict1` на `{‘a’: 1, ‘b’: 3, ‘c’: 4}`. Этот метод не создаёт новый словарь, а изменяет существующий. Если вам нужно сохранить оригинальные словари неизменными, лучше использовать другие способы сложения, такие как оператор `|` или распаковка словарей.
Как использовать распаковку словарей для их сложения?
Распаковка словарей — это способ объединения словарей с помощью оператора `**`. Он появился в Python 3.5 и позволяет создать новый словарь, комбинируя элементы из нескольких словарей. Например, чтобы объединить два словаря `dict1 = {‘a’: 1, ‘b’: 2}` и `dict2 = {‘b’: 3, ‘c’: 4}`, можно использовать следующий синтаксис: `new_dict = {**dict1, **dict2}`. В результате получим новый словарь `{‘a’: 1, ‘b’: 3, ‘c’: 4}`. Важно отметить, что если ключи в словарях совпадают, то значение из второго словаря перезапишет значение из первого.
Что будет, если при сложении словарей используются одинаковые ключи?
При объединении словарей в Python, если в них есть одинаковые ключи, то значение из второго словаря перезапишет значение из первого. Это касается всех методов сложения: оператора `|`, метода `.update()` и распаковки через `**`. Например, если есть два словаря: `dict1 = {‘a’: 1, ‘b’: 2}` и `dict2 = {‘b’: 3, ‘c’: 4}`, то результат при использовании любого из этих методов будет такой: `{‘a’: 1, ‘b’: 3, ‘c’: 4}`, где значение для ключа `’b’` будет взято из второго словаря. Этот подход позволяет избежать дублирования ключей в итоговом словаре.
