Python

Dict comprehension в Python: генератор словарей

Dict comprehension — это способ собрать словарь в одну понятную конструкцию. Он похож на list comprehension, но создает пары ключ: значение

Используйте его, когда нужно превратить список в словарь, изменить значения, отфильтровать элементы или быстро подготовить справочник

Базовый синтаксис

words = ["python", "sql", "html"]

lengths = {word: len(word) for word in words}

print(lengths)

Слева от for записана пара ключ: значение. В примере ключом становится слово, а значением — длина слова

Словарь из списка объектов

Частая задача — сделать быстрый доступ по идентификатору

users = [
    {"id": 1, "name": "Анна"},
    {"id": 2, "name": "Илья"},
]

users_by_id = {user["id"]: user for user in users}

print(users_by_id[2]["name"])

Такой прием полезен, когда дальше нужно быстро находить запись по ключу

Фильтрация

Условие после for оставляет только подходящие элементы

prices = {"tea": 120, "coffee": 250, "juice": 180}

expensive = {name: price for name, price in prices.items() if price >= 180}

print(expensive)

Если условие становится сложным, лучше сначала написать обычный цикл. Comprehension должен оставаться читаемым

Изменение ключей и значений

Можно одновременно нормализовать ключи и пересчитать значения

raw = {" Tea ": "120", "Coffee": "250"}

prices = {name.strip().lower(): int(price) for name, price in raw.items()}

print(prices)

Такой пример часто встречается при обработке данных из файлов, форм и таблиц

Когда лучше обычный цикл

Обычный цикл лучше, если внутри много проверок, несколько веток, логирование или обработка ошибок

raw = ["tea:120", "bad row", "coffee:250"]
prices = {}

for row in raw:
    if ":" not in row:
        continue
    name, price = row.split(":", 1)
    prices[name] = int(price)

print(prices)

Такой код длиннее, зато его проще отладить

Пример: индекс пользователей по id

Dict comprehension часто нужен, когда список записей нужно превратить в быстрый поиск по ключу

users = [
    {"id": 1, "name": "Анна"},
    {"id": 2, "name": "Илья"},
]

users_by_id = {user["id"]: user for user in users}

print(users_by_id[2]["name"])

В списке пришлось бы искать пользователя циклом. В словаре доступ по id получается прямым

Пример: изменить ключи и отфильтровать данные

prices = {"coffee": 250, "tea": 180, "water": 0}

visible_prices = {
    name.upper(): price
    for name, price in prices.items()
    if price > 0
}

print(visible_prices)

Здесь одновременно меняются ключи и фильтруются значения. Если выражение стало длинным, лучше развернуть его в обычный цикл

Когда comprehension лучше не писать

Не используйте dict comprehension, если внутри нужно много условий, логирование, обработка ошибок или несколько промежуточных шагов. В таких случаях обычный цикл читается честнее

Частые ошибки

Перепутать ключ и значение

В {key: value for ...} до двоеточия идет ключ, после двоеточия — значение

Потерять данные из-за повторяющихся ключей

Если два элемента дают один и тот же ключ, последнее значение заменит предыдущее

Делать слишком длинную строку

Если comprehension трудно читать вслух, перепишите его обычным циклом

Практика

Сделайте словарь цен из списка строк ["tea:120", "coffee:250"]. Затем добавьте строку без двоеточия и решите, оставить comprehension или перейти на цикл

Часто задаваемые вопросы

Можно ли использовать if else внутри dict comprehension?

Да, но для новичка такой код быстро становится тяжелым. Если условие сложное, лучше обычный цикл

Почему в словаре стало меньше элементов?

Скорее всего, повторились ключи. Словарь хранит одно значение на один ключ

Dict comprehension быстрее цикла?

Часто он компактнее и может быть быстрее, но читаемость важнее небольшой разницы в скорости

Когда dict comprehension лучше цикла

Dict comprehension хорош, если преобразование короткое и читается вслух: из слова сделать длину, из пользователя сделать пару id → пользователь, из цены оставить только дорогие товары

words = ["python", "sql", "html"]
lengths = {word: len(word) for word in words}

print(lengths)

Если внутри появляется несколько условий, обработка ошибок и промежуточные переменные, обычный цикл часто понятнее

rows = ["tea:120", "bad row", "coffee:250"]
prices = {}

for row in rows:
    if ":" not in row:
        continue
    name, price = row.split(":", 1)
    prices[name] = int(price)

print(prices)

По этой теме полезно отдельно посмотреть Составьте еженедельное расписание занятий, чтобы расширить контекст и сравнить подходы

По этой теме полезно отдельно посмотреть Аннотации типов для декораторов в Python, чтобы расширить контекст и сравнить подходы

Подписаться
Уведомить о
guest
0 комментариев
Старые
Новые Популярные

Настройки cookie

0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x