Kodokon kodokon.com

Списковые и словарные включения

Замени циклы, которые строят коллекции, выразительными включениями, чтобы преобразовывать, фильтровать и переиндексировать данные.

8 мин · 3 вопросов

Открыть этот урок в Kodokon

Списковое включение сжимает самый частый паттерн в программировании: построение списка путём преобразования или фильтрации последовательности. Синтаксис читается как фраза: [expression for element in sequence if condition]. Результат тот же, что у цикла с append, но в одной декларативной строке, которую любой Python-разработчик узнаёт мгновенно.

PYTHON
prices = [12.0, 49.9, 5.5, 199.0]

with_tax = [round(p * 1.2, 2) for p in prices]
cheap = [p for p in prices if p < 50]

print(with_tax)  # [14.4, 59.88, 6.6, 238.8]
print(cheap)     # [12.0, 49.9, 5.5]
Преобразуй выражением, фильтруй с помощью if в конце.

Словарное включение следует той же логике с синтаксисом {key: value for ...}. Очень частый сценарий в проектах: переиндексация списка объектов по их идентификатору, чтобы потом обращаться к ним мгновенно, а не пробегать список каждый раз, когда что-то нужно.

PYTHON
users = [
    {"id": 7, "name": "Alice"},
    {"id": 12, "name": "Bruno"},
    {"id": 31, "name": "Chloe"},
]

by_id = {u["id"]: u["name"] for u in users}
print(by_id[12])    # Bruno
print(31 in by_id)  # True
Переиндексация по идентификатору - классика профессионального кода.

Две позиции для if - две разные роли. Поставленный после for, он фильтрует: отсеянные элементы в результат не попадают. Поставленный перед for, как условное выражение (a if condition else b), он выбирает значение для каждого элемента: тогда список сохраняет ту же длину, что и исходный.

PYTHON
scores = [45, 82, 67, 91]

labels = ["pass" if s >= 60 else "fail" for s in scores]
print(labels)  # ['fail', 'pass', 'pass', 'pass']
Условное выражение преобразует каждый элемент, не удаляя ни одного.

Проверка знаний

Убедись, что запомнил ключевые моменты этого урока.

  1. Какова роль if в [x * 2 for x in data if x > 0]?
    • Он выбирает между двумя значениями для каждого элемента
    • Он фильтрует: остаются только положительные элементы
    • Он останавливает включение на первом отрицательном элементе
  2. Что даёт {n: n * n for n in range(3)}?
    • {0: 0, 1: 1, 2: 4}
    • {1: 1, 2: 4, 3: 9}
    • [0, 1, 4]
    • {0, 1, 4}
  3. Когда лучше заменить включение обычным циклом?
    • Когда логика становится сложной или вложенной
    • Как только в списке больше сотни элементов
    • Никогда, включение всегда предпочтительнее