Python
Как объединить два словаря в Python
Объединение словарей нужно, когда у вас есть базовые настройки и пользовательские настройки, старые и новые данные, два источника информации или несколько частей одной карточки
Главный вопрос не в том, какой синтаксис короче. Важно понять, что делать при совпадении ключей: оставить старое значение, заменить новым или обработать конфликт отдельно
По этой теме полезно отдельно посмотреть Составьте еженедельное расписание занятий, чтобы расширить контекст и сравнить подходы
По этой теме полезно отдельно посмотреть Аннотации типов для декораторов в Python, чтобы расширить контекст и сравнить подходы
Оператор |
В современных версиях Python два словаря удобно объединять через оператор |
base = {"theme": "light", "language": "ru"}
user = {"theme": "dark", "limit": 20}
result = base | user
print(result)
print(base)
Если ключ совпадает, побеждает значение из правого словаря. В примере theme станет dark, а исходный base не изменится
Распаковка через двойную звездочку
Старый и до сих пор понятный вариант — распаковка
base = {"theme": "light", "language": "ru"}
user = {"theme": "dark", "limit": 20}
result = {**base, **user}
print(result)
Правило совпадения ключей такое же: последнее значение перезаписывает предыдущее
update меняет исходный словарь
Метод update() подходит, когда нужно изменить словарь на месте
settings = {"theme": "light", "language": "ru"}
settings.update({"theme": "dark", "limit": 20})
print(settings)
Это удобно для настроек, но опасно, если исходный словарь еще нужен в прежнем виде. Если сомневаетесь, создайте копию
base = {"theme": "light", "language": "ru"}
result = base.copy()
result.update({"theme": "dark"})
print(base)
print(result)
Как заметить конфликт ключей
Иногда нельзя молча перезаписывать значения. Например, два источника прислали разные цены
first = {"price": 1000, "title": "Курс"}
second = {"price": 1200, "currency": "RUB"}
conflicts = set(first) & set(second)
print(conflicts)
После этого можно решить, что делать: выбрать новое значение, оставить старое, записать конфликт в лог или показать человеку
Объединение вложенных словарей
Обычное объединение не сливает вложенные словари глубоко. Оно заменяет значение целиком
base = {"seo": {"title": "Старый", "description": "Описание"}}
new = {"seo": {"title": "Новый"}}
print(base | new)
Если нужно сохранить description, объединяйте вложенный словарь отдельно
base = {"seo": {"title": "Старый", "description": "Описание"}}
new = {"seo": {"title": "Новый"}}
seo = base["seo"] | new["seo"]
result = base | {"seo": seo}
print(result)
Что выбрать: оператор, update или распаковку
| Ситуация | Вариант | |
|---|---|---|
| нужен новый словарь в Python 3.9+ | `result = first | second` |
| нужно поддержать старую версию Python | result = {first, second} |
|
| нужно изменить исходный словарь | first.update(second) |
|
| нужно увидеть совпадающие ключи | first.keys() & second.keys() |
|
| есть вложенные словари | объединить вложенный уровень отдельно |
Для учебного кода удобнее начинать с |: он хорошо читается и не меняет исходные словари. update() оставляйте для случаев, когда изменение на месте действительно нужно
Практика: собрать настройки приложения
defaults = {"theme": "light", "language": "ru", "limit": 10}
profile = {"theme": "dark"}
runtime = {"limit": 50}
settings = defaults | profile | runtime
changed = defaults.keys() & (profile.keys() | runtime.keys())
print(settings)
print("изменены:", changed)
Порядок важен: чем правее словарь, тем выше его приоритет. Такой подход часто используют для настроек, где есть значения по умолчанию, настройки пользователя и временные параметры запуска
Частые ошибки
Не понимать, какой словарь побеждает
В base | user значение из user заменит значение из base при одинаковом ключе
Менять исходные настройки случайно
update() меняет словарь на месте. Для безопасной сборки результата используйте copy(), | или распаковку
Ждать глубокого объединения
Python не объединяет вложенные словари автоматически. Если внутри лежит еще один словарь, его нужно обрабатывать отдельно
Практика
Соберите defaults, user_settings и runtime_settings. Объедините их так, чтобы самые свежие настройки были последними. Затем отдельно выведите список ключей, которые были перезаписаны
Часто задаваемые вопросы
Какой способ лучше использовать новичку?
Для нового словаря чаще всего удобен base | other. Для изменения существующего словаря подходит update()
Как сохранить исходный словарь?
Используйте result = base | other или сделайте copy() перед update()
Что делать при одинаковых ключах?
Заранее решите правило: новое значение побеждает, старое сохраняется или конфликт нужно показать отдельно
Как объединять без потери вложенных данных
Обычное объединение заменяет значение целиком. Если внутри лежит вложенный словарь, часть полей может потеряться
base = {"seo": {"title": "Старый", "description": "Описание"}}
new = {"seo": {"title": "Новый"}}
bad = base | new
print(bad)
seo = base["seo"] | new["seo"]
good = base | {"seo": seo}
print(good)
Если вложенных уровней много, лучше написать отдельную функцию или использовать проверенную библиотеку. Для новичка важно запомнить: оператор | не делает глубокое объединение сам по себе
Проверка совпадающих ключей
Перед объединением можно найти ключи, которые есть в обоих словарях
base = {"theme": "light", "limit": 10}
user = {"limit": 20, "language": "ru"}
overlap = base.keys() & user.keys()
print(overlap)