Программирование и IT

Python: словари

Словарь хранит пары «ключ — значение» и находит значение по ключу за постоянное время независимо от размера. Это рабочая лошадка для подсчётов, группировок и настроек. Разберём создание, безопасный доступ, перебор и места, где словарь ведёт себя не так, как ожидают.

Обновлено
В этой статье

Создание и требования к ключу#

prices = {"чай": 120, "кофе": 250}
empty = {}                      # именно словарь, а не множество
from_pairs = dict([("a", 1), ("b", 2)])
print(prices["чай"], len(prices))   # 120 2

Ключом может быть только неизменяемое значение: строка, число, кортеж,
логическое. Список ключом быть не может — попытка даёт TypeError: unhashable type: 'list'. Значением может быть что угодно, включая другой словарь.

Порядок вставки сохраняется: начиная с Python 3.7 это не случайность
реализации, а гарантия языка. Перебор словаря даёт ключи в том порядке, в
котором их добавляли.

Доступ без KeyError#

Квадратные скобки при отсутствии ключа бросают KeyError. Когда отсутствие
ключа — нормальная ситуация, берут get:

print(prices.get("какао"))        # None
print(prices.get("какао", 0))     # 0
print("какао" in prices)          # False
prices["какао"] = 90              # добавление — тоже через скобки

Оператор in проверяет именно ключи, а не значения; для значений нужен
in prices.values().

Родственный метод setdefault возвращает значение по ключу, а если ключа нет —
кладёт указанное и возвращает его. Это удобно для группировки:

groups = {}
for word in ["ель", "ёж", "сосна", "сова"]:
    groups.setdefault(word[0], []).append(word)
print(groups)   # {'е': ['ель'], 'ё': ['ёж'], 'с': ['сосна', 'сова']}

Перебор и три представления#

for key in prices:
    print(key, prices[key])

for key, value in prices.items():
    print(key, "", value)

print(list(prices.keys()))     # ['чай', 'кофе', 'какао']
print(sum(prices.values()))    # 460

keys(), values() и items() возвращают не списки, а представления: они
«смотрят» на живой словарь и отражают изменения. Если нужен именно список —
оберни в list().

Сортировка словаря даёт список пар, а не словарь:

top = sorted(prices.items(), key=lambda kv: kv[1], reverse=True)
print(top)        # [('кофе', 250), ('чай', 120), ('какао', 90)]
print(dict(top))  # обратно в словарь, если нужен словарь

Изменение, удаление, слияние#

prices.update({"чай": 130, "сок": 100})
print(prices)   # {'чай': 130, 'кофе': 250, 'какао': 90, 'сок': 100}

removed = prices.pop("какао")
print(removed)              # 90
print(prices.pop("нет", 0)) # 0 вместо KeyError
del prices["сок"]

update перезаписывает существующие ключи и добавляет новые. С Python 3.9 есть
оператор слияния: a | b даёт новый словарь, а a |= b меняет a на месте.
При совпадении ключа побеждает правый словарь.

Словарное выражение строится как списочное, но с парой через двоеточие:

squares = {n: n * n for n in range(4)}
print(squares)          # {0: 0, 1: 1, 2: 4, 3: 9}
swapped = {v: k for k, v in squares.items()}
print(swapped[9])       # 3

Где ломается#

Добавление во время перебора. Изменение размера словаря внутри цикла по
нему даёт RuntimeError: dictionary changed size during iteration. Собирай
изменения отдельно или перебирай копию: for k in list(d).

Одинаковые ключи в литерале. {"a": 1, "a": 2} — не ошибка, останется
{'a': 2}: последнее присваивание побеждает молча.

True и 1 — один ключ. Ключи сравниваются по значению, а 1 == True,
поэтому {1: "раз", True: "да"} схлопнется в один элемент со значением "да".

Подсчёт через get. Типичная задача — частоты. Без словаря она разрастается
в десяток строк, а так укладывается в три:

counts = {}
for ch in "абракадабра":
    counts[ch] = counts.get(ch, 0) + 1
print(counts)   # {'а': 5, 'б': 2, 'р': 2, 'к': 1, 'д': 1}

Попробуй сам: посчитай частоты слов в тексте и выведи три самых частых
через sorted с key. Для работы с текстом пригодятся
строки, а когда порядок важнее ключей —
списки.

План по этапам

  1. Словарь настроекСоздать словарь из пяти пар, вывести значение по ключу и длину.
  2. Безопасный доступСравнить d["нет"] и d.get("нет", 0): первый вызов должен дать KeyError.
  3. Перебор itemsВывести все пары в формате «ключ → значение» через items().
  4. Частоты символовПосчитать, сколько раз каждый символ встречается в строке, через get.
  5. Сортировка по значениюОтсортировать пары по убыванию значения и вывести первые три.

Начать изучать эту тему у себя

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

Начать план

Проверь себя

1.Что выведет: d = {"a": 1}; print(d.get("b", 0))?

2.Что выведет print(len({"a": 1, "b": 2, "a": 3}))?

3.Что выведет: d = {"x": 1}; print("x" in d, 1 in d)?

4.Сколько раз буква «а» встречается в строке «абракадабра»?

Источники

Было полезно?

Ещё темы

Программирование и IT Python: строки Строка в Python — неизменяемая последовательность символов. Из этого следуют почти все её особенности: методы не меняют строку, а возвращают новую, а быстрая сборка текста идёт через join, а не через сложение в цикле. Ниже — рабочий минимум с примерами и выводом. Программирование и IT Python: списки Список — изменяемый упорядоченный набор значений произвольных типов. Он же главный источник неожиданностей у начинающих: присваивание не копирует список, sort ничего не возвращает, а удаление элементов прямо в цикле пропускает половину. Разберём по порядку. Программирование и IT git branch Ветка в git — это подвижный указатель на коммит, а не копия файлов. Поэтому завести её ничего не стоит, а команда git branch отвечает за список веток, их создание, переименование и удаление. Программирование и IT Как изучить Python с нуля Python хорош для первого знакомства с программированием: код читается почти как текст, а стандартная библиотека закрывает большинство бытовых задач. Этот план ведёт от установки интерпретатора до собственных скриптов, покрытых тестами, — примерно за четыре месяца при занятиях около часа в день. Программирование и IT Python: задачи с решениями Подборка задач по возрастанию сложности — от разворота строки до генератора и декоратора-счётчика. Сначала решай сам и только потом открывай разбор: сравнение своего кода с чужим даёт больше, чем чтение готового. Все решения проверены на Python 3. Программирование и IT Python: срезы Срез вырезает из последовательности кусок по правилу «с какого индекса, до какого, с каким шагом». Запись компактная, но у неё два места, где почти все ошибаются: правая граница не включается, а при отрицательном шаге границы меняются местами. Разберём оба.

Ещё сценарии