Как создать словарь в Python с ключами-строками и числовыми значениями
Что проверяют
Базу по словарям, но с прицелом на детали: способы создания, что может быть ключом и как безопасно читать отсутствующий ключ. Следом обычно спрашивают про сложность доступа и порядок элементов.
Как отвечать
Способы создания и когда каждый уместен:
- литерал:
prices = {"apple": 120, "banana": 85}. Самый частый и быстрый вариант; dict()с именованными аргументами:dict(apple=120). Работает, только если ключ годится как имя переменной, строку"red-apple"так не передать;- из пар:
dict(zip(names, amounts))илиdict([("apple", 120)]); - генератор словаря:
{name: len(name) for name in names}; - одинаковое начальное значение:
dict.fromkeys(names, 0); - счётчики:
collections.Counter(words)илиdefaultdict(int), когда значения копятся в цикле.
Аннотация типа: dict[str, int] (встроенные дженерики работают с Python 3.9) или dict[str, float], если значения дробные. Для записи с фиксированным набором полей подходит TypedDict.
Что стоит сказать сверху. Ключ должен быть хешируемым: строки, числа и кортежи из неизменяемых элементов подходят, список нет. Доступ по ключу в среднем O(1), под капотом хеш-таблица. Порядок вставки гарантированно сохраняется начиная с Python 3.7. Отсутствующий ключ через d["x"] даёт KeyError, а d.get("x", 0) вернёт значение по умолчанию.
Где спотыкаются
Удаляют или добавляют ключи в цикле for key in d. Python падает с RuntimeError: dictionary changed size during iteration. Итерируйтесь по копии list(d) или соберите новый словарь генератором.
Используют dict.fromkeys(keys, []) по аналогии с нулём. Для чисел всё в порядке, а список окажется одним объектом на все ключи, и добавление в один «размножится» на остальные.
Пишут counts[word] += 1 для нового ключа и получают KeyError. Нужен counts.get(word, 0) + 1, defaultdict(int) или Counter, и хорошо бы объяснить разницу: defaultdict создаёт ключ даже при простом чтении, а Counter возвращает 0, ничего не добавляя.