Перейти к содержанию

412 уроков, 25 библиотек и челлендж «Что выведет код?» — бесплатно, код прямо в браузере

Начать обучение
Урок 5 из 20 Начальный 15 мин 100 XP

Добавление и изменение пар в словаре

Одна операция на всё: d[ключ] = значение добавляет новую пару или заменяет старую. Плюс уникальность ключей, порядок вставки и счётчики, которые пишутся в одну строку.

Редакция Питоники

Словарь из первого урока был собран целиком, одной записью в фигурных скобках. В жизни так бывает редко: товары поступают по одному, оценки появляются по мере учёбы, настройки меняются на ходу. Хорошая новость: для добавления и изменения пар в Python одна и та же операция — присваивание по ключу.

Новая пара: d[ключ] = значение

Записываем ключ в квадратных скобках, справа — значение. Если такого ключа в словаре ещё нет, рождается новая пара. Присваивание по ключу делает обе работы: новой пары нет — она появится, пара есть — значение заменится.

добавляем пары по одной
stock = {'молоко': 12}

stock['хлеб'] = 5
stock['сыр'] = 8

print(stock)
Вывод
{'молоко': 12, 'хлеб': 5, 'сыр': 8}

Новые пары встают в конец — и печатаются в том же порядке. Словарь помнит порядок вставки: сначала добавили 'хлеб', потом 'сыр' — в этом порядке они и живут. Так пустой словарь {} из урока про создание превращается в полноценный справочник, пара за парой.

Тот же ключ — другая работа

перезапись значения
stock = {'молоко': 12, 'хлеб': 5}

stock['молоко'] = 10

print(stock)
Вывод
{'молоко': 10, 'хлеб': 5}
  • ключа ещё нет — пара добавляется в конец словаря;
  • ключ уже есть — значение заменяется, позиция пары и остальные пары не трогаются;
  • третьего не дано: двух пар с одним ключом в словаре не бывает никогда.
дубликат ключа в литерале
prices = {'молоко': 89, 'молоко': 99}

print(prices)
print(len(prices))
Вывод
{'молоко': 99}
1

Уникальность ключей — не причуда, а фундамент всей адресации словаря: имя ведёт ровно к одному значению, поэтому поиск по ключу однозначен. Типичный рабочий сценарий перезаписи — обновление по свежим данным: цена изменилась, счёт вырос. Новое значение часто считают от старого — читают по ключу и тут же записывают обратно; у прибавления есть и короткая запись +=. Ключ при этом должен существовать, иначе чтение упадёт: как проверить его заранее — в уроке про in.

обновить значение от старого
score = {'Анна': 12}

score['Анна'] = score['Анна'] + 3

print(score)
Вывод
{'Анна': 15}

Замена не двигает пару на новое место

Вот место, где словарь ведёт себя не так, как ожидают. Многие думают, что присваивание по существующему ключу «пересоздаёт» пару, и та встаёт в конец. Нет: пара сохраняет свою позицию, меняется только значение. Проверяется это просто.

позиция пары не меняется
cart = {}
cart['чай'] = 1
cart['кофе'] = 2
cart['чай'] = 3

print(cart)
print(list(cart))
Вывод
{'чай': 3, 'кофе': 2}
['чай', 'кофе']

Чай остался первым, хотя его перезаписали последним. Словарь помнит не «последнее действие», а «порядок первого появления ключа». Это отличает словарь от обычного объекта с перезаписью и, кстати, ровно поэтому обновление цены в прайсе не сбрасывает позицию товара в выгрузке.

Счётчик в одну строку

Самый частый сценарий, где словарь применяют в реальном коде, — подсчёт. Слов в тексте, голосов в опросе, покупок в заказе. Ручной вариант выглядит так: взять значение, прибавить единицу, записать обратно. Чтобы не падать на первом же новом слове, старое значение нужно доставать с умолчанием.

считаем слова
words = ['чай', 'кофе', 'чай']
count = {}

for w in words:
    count[w] = count.get(w, 0) + 1

print(count)
Вывод
{'чай': 2, 'кофе': 1}

Это рабочий код, но писать его руками каждый раз лень. Ровно для таких мест в стандартной библиотеке есть Counter — словарь, который считает сам: в уроке 11 разбираем его подробно. А defaultdict(int) из урока 12 умеет то же самое ещё короче: счётчик стартует с нуля сам, и строка превращается в count[w] += 1 без всякого .get.

Обратите внимание на +=. Это не отдельная операция словаря, а сокращение Python: score['Анна'] += 3 разворачивается в score['Анна'] = score['Анна'] + 3. И тут скрыта ловушка — прочитать значение приходится раньше, чем записать, а значит, ключ обязан существовать. Для счётчика, где ключ может появиться впервые, += не подходит: он уронит программу с KeyError. Либо get с нулём, либо defaultdict.

+= работает только для существующего ключа
score = {'Анна': 12, 'Борис': 9}

score['Анна'] += 3
score['Борис'] += 1

print(score)
Вывод
{'Анна': 15, 'Борис': 10}

Удаление дешёвых позиций

Присваивание умеет и обратное: del d[ключ] убирает пару целиком. Нюанс в том, что нельзя удалять прямо во время обхода словаря — Python ломает обход с RuntimeError. Если нужно вычистить дешёвые позиции, сначала соберите ключи-кандидаты в список и удаляйте после цикла.

чистим дешёвое, не ломая обход
prices = {'молоко': 89, 'хлеб': 42}

for name in list(prices.keys()):
    if prices[name] < 50:
        del prices[name]

print(prices)
Вывод
{'молоко': 89}

Обёртка list(...) — обязательная часть приёма. Она делает копию ключей, по которой цикл идёт уже без оглядки на словарь: удалять из оригинала во время такого обхода можно спокойно. Подробнее про запрет менять словарь во время перебора — в уроке 8.

Что дальше

Добавлять и менять пары вы умеете. Обратная операция — удаление — в уроке 6: там четыре инструмента (del, pop, popitem, clear) и разница между ними, которая на практике важнее, чем кажется. А чтобы не гадать, есть ли ключ вообще, — урок 7 про оператор in.

Шпаргалка: добавить, изменить, удалить

Что хотимЗаписьЧто получится
Добавить паруd['хлеб'] = 5новая пара в конце словаря
Изменить значениеd['хлеб'] = 8старое значение заменено, позиция та же
Увеличить на 3d['хлеб'] += 3значение плюс 3, ключ обязан существовать
Прибавить к заданномуd['хлеб'] = d.get('хлеб', 0) + 3работает и для нового ключа
Удалить паруdel d['хлеб']пара исчезнет, ничего не вернётся
Удалить и забратьprice = d.pop('хлеб')значение попадёт в переменную

Самая частая ошибка при работе с парами — не в синтаксисе, а в ожиданиях. Первый сюрприз: перезапись не переносит пару на новое место, второй: += требует существующего ключа, третий: дубликат ключа в данных исчезает без следа. Все три мы разобрали — теперь ясно, где искать, если что-то пойдёт не так.

Что выведет код?

Сначала предскажи ответ в голове — это главный навык программиста.

cart = {'чай': 1}

cart['кофе'] = 2
cart['чай'] = 3

print(cart)
d = {}
d['a'] = 1
d['a'] = 2
d['b'] = 3

print(len(d))
print(d)
score = {'Борис': 10}

score['Борис'] += 5

print(score)
Проверь себя
0 / 8

1. Как добавить в словарь stock новую пару: ключ 'сыр', значение 8?

2. Ключ 'молоко' уже есть в словаре. Что сделает stock['молоко'] = 10?

3. Куда встаёт новая пара при добавлении?

4. Что окажется в словаре после prices = {'молоко': 89, 'молоко': 99}?

5. Что делает запись score['Анна'] += 3?

6. Что произойдёт с парой 'чай', если перезаписать её значение в словаре, где она стояла первой?

7. Почему score['Анна'] += 3 упадёт с KeyError, если ключа 'Анна' в словаре нет?

8. Как посчитать слова в списке, не падая на первом новом слове?

Карточки терминов
Запомнено: 0 / 8
Практика

Дан словарь cart = {'чай': 1}. Добавь кофе в количестве 2, затем обнови чай до 3. Выведи словарь.

practice.py
Вопросы и ответы по уроку

Как добавить элемент в словарь в Python?

Присваиванием по ключу: stock['сыр'] = 8. Если ключа ещё не было, появится новая пара в конце словаря; если ключ существовал — его значение заменится. Отдельного метода add у словаря нет: присваивание делает обе работы.

Урок 2: создание словаря

Что будет, если добавить ключ, который уже есть?

Значение просто заменится: вторая пара не создастся, потому что ключи в словаре уникальны. Позиция пары и остальные пары при этом не меняются — меняется только значение.

Почему {'молоко': 89, 'молоко': 99} не вызывает ошибку?

Дубликат ключа в литерале разрешён и обрабатывается молча: пары с одинаковыми ключами запрещены, поэтому вторая запись перезаписывает первую — останется {'молоко': 99}. Это удобный механизм, но и ловушка: опечатка-дубликат не выдаст себя сообщением.

Как изменить значение в словаре, оттолкнувшись от старого?

Прочитать и записать в одном выражении: score['Анна'] = score['Анна'] + 3, короче — score['Анна'] += 3. Ключ при этом должен существовать, иначе чтение упадёт с KeyError — сначала проверьте его через get или in.

Урок 7: проверка ключа оператором in

Сдвигается ли пара в словаре, если перезаписать её значение?

Нет. Словарь помнит порядок первого появления ключа, поэтому перезапись меняет только значение, а позиция пары остаётся прежней. Если порядок важен — например, при выгрузке в CSV, — задавайте его явно через sorted.

Урок 13: сортировка словаря

Как посчитать, сколько раз встретился каждый элемент списка?

Циклом с обновлением по ключу: count[w] = count.get(w, 0) + 1. Второй вариант — готовое решение из стандартной библиотеки: Counter(words) из модуля collections. Третий — defaultdict(int), который сам создаёт нулевое значение для нового ключа.

Урок 11: Counter

Почему нельзя удалять пары прямо во время цикла по словарю?

Python запрещает менять размер словаря посреди обхода: он прервёт программу с RuntimeError: dictionary changed size during iteration. Спасает обёртка list(prices.keys()) — цикл идёт по копии ключей, и удалять из оригинала во время обхода уже можно.

Урок 8: перебор словаря

Понравился урок? Сошлитесь на него

«Присваивание по ключу делает обе работы: новой пары нет — она появится, пара есть — значение заменится.»

Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.

TelegramVK

Что дальше

Осталось в разделе: 20 из 20. Прогресс хранится в вашем браузере.

Похожие уроки по темам

Подобраны автоматически по пересечению тем и ключевых слов.