Как увеличить все значения в словаре Python на 2
Что проверяют
Простой вопрос проверяет, различаете ли вы создание нового словаря и изменение существующего и понимаете ли, что можно делать со словарём во время обхода. Следом часто спрашивают, что делать, если значения не все числовые или словарь вложенный.
Как отвечать
Сначала уточните, нужен новый словарь или правка на месте, от этого зависит решение:
- новый словарь:
{k: v + 2 for k, v in data.items()}. Исходник не меняется, это важно, если на него ссылаются другие части кода; - на месте:
for k in data: data[k] += 2. Присваивание по существующему ключу не меняет размер словаря, поэтому такой обход безопасен; - смешанные значения:
{k: v + 2 if isinstance(v, (int, float)) else v for k, v in data.items()}. Без проверки строка илиNoneдадутTypeError, и лучше заранее решить, пропускать такие значения или падать; - вложенные словари: рекурсивная функция, которая для значения типа
dictвызывает себя, а для числа прибавляет 2; - много числовых данных: если это на самом деле таблица, её место в
numpyилиpandas, гдеseries + 2векторизовано и работает на порядок быстрее цикла.
Сложность в обоих основных вариантах O(n) по времени, новый словарь дополнительно занимает O(n) памяти. Порядок ключей сохраняется: начиная с Python 3.7 порядок вставки в словаре гарантирован спецификацией языка.
Где спотыкаются
Добавляют или удаляют ключи в том же цикле, по которому идут, и получают RuntimeError: dictionary changed size during iteration. Менять значения можно, менять набор ключей нельзя; если нужно и то и другое, обходят копию list(data.items()).
Пишут for v in data.values(): v += 2 и удивляются, что словарь не изменился. Целые числа неизменяемы, v просто переназначается на новый объект, а в словаре остаётся старая ссылка.
Забывают, что bool это подкласс int: проверка isinstance(v, int) пропустит True, и в словаре окажется 3. Если флаги и числа хранятся вместе, bool исключают явно.