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

⏱ 25 мин · 🧩 заданий: 5

Списковое включение

Вместо цикла с append:

squares = []
for x in range(10):
    squares.append(x * x)
print(squares)

squares = [x * x for x in range(10)]     # то же самое одной строкой
print(squares)

Общая форма: [выражение for элемент in итерируемое if условие].

[ x * x for x in range(10) if x % 2 == 0 ] ───┬── ─────────┬───────── ──────┬────── что откуда берём фильтр (необязательно) кладём
words = ["Python", "is", "AWESOME", "and", "fun"]
print([w.lower() for w in words])
print([w for w in words if len(w) > 3])
print([len(w) for w in words if w.isupper()])

Условие до и после for

nums = [-2, 5, -1, 8]
print([x for x in nums if x > 0])               # фильтр: if после for
print([x if x > 0 else 0 for x in nums])        # преобразование: тернарный оператор до for

Как не перепутать

if после for — отбрасывает элементы (результат короче). if ... else до for — выбирает значение для каждого элемента (длина та же).

Вложенные циклы

Порядок for — такой же, как во вложенных циклах:

pairs = [(x, y) for x in range(3) for y in "ab"]
print(pairs)
# эквивалент:
# for x in range(3):
#     for y in "ab":
#         pairs.append((x, y))

matrix = [[1, 2, 3], [4, 5, 6]]
flat = [x for row in matrix for x in row]
transposed = [[row[i] for row in matrix] for i in range(3)]
print(flat, transposed)

Словарные и множественные включения

words = ["кот", "собака", "ёж", "кот"]
lengths = {w: len(w) for w in words}            # dict
unique_lengths = {len(w) for w in words}        # set
inverted = {v: k for k, v in {"a": 1, "b": 2}.items()}
print(lengths, unique_lengths, inverted)

Генераторные выражения

С круглыми скобками получается не кортеж, а генератор — ленивая последовательность, которая вычисляет элементы по одному:

gen = (x * x for x in range(5))
print(gen)
print(next(gen), next(gen), list(gen))   # элементы выдаются по требованию
print(list(gen))                          # генератор одноразовый — уже пуст

print(sum(x * x for x in range(1_000_000)))   # без промежуточного списка в памяти
print(any(n > 100 for n in [5, 300, 7]))       # останавливается на первом True

Если генераторное выражение — единственный аргумент функции, вторые скобки не нужны: sum(x for x in ...). Подробно генераторы — в модуле «Итераторы и генераторы».

Своя область видимости

В Python 3 переменная цикла внутри включения не «утекает» наружу:

x = "снаружи"
squares = [x * x for x in range(3)]
print(x)           # "снаружи" — включение не перезаписало x

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

Включения хороши для простых преобразований и фильтров. Пишите обычный цикл, если:

  • логика сложная — несколько условий, промежуточные переменные, try/except;
  • больше двух уровней вложенности;
  • нужен побочный эффект (печать, запись в файл) — включение не для этого.
# плохо: включение ради побочного эффекта
[print(x) for x in items]

# хорошо
for x in items:
    print(x)

Итог

  • [expr for x in it if cond] — список; {k: v for ...} — словарь; {expr for ...} — множество.
  • if после for фильтрует, a if c else b до for преобразует.
  • Несколько for — в порядке вложенных циклов.
  • (expr for ...) — ленивый генератор: экономит память, одноразовый.
  • Сложная логика — обычный цикл.

Практика решено 0 из 5

Вы не вошли — ответы проверяются, но прогресс не сохранится. Войти или зарегистрироваться.
Задание 1 Программа на Python

Одной строкой (через включение) создайте список evens_squared — квадраты чётных чисел от 1 до 20.

Какие тесты проверяют код (1)
assert evens_squared == [4, 16, 36, 64, 100, 144, 196, 256, 324, 400]
Задание 2 Программа на Python

Напишите функцию flatten(matrix), которая превращает список списков в плоский список с помощью одного спискового включения с двумя for.

Какие тесты проверяют код (2)
assert flatten([[1, 2], [3], [], [4, 5]]) == [1, 2, 3, 4, 5]
assert flatten([]) == []
Задание 3 Программа на Python

Напишите функцию price_with_tax(prices): на вход словарь «товар → цена», на выход — новый словарь с ценами, увеличенными на 20% и округлёнными до 2 знаков, только для товаров дороже 100. Используйте словарное включение.

Какие тесты проверяют код (2)
assert price_with_tax({"кофе": 200, "жвачка": 50, "чай": 150.5}) == {"кофе": 240.0, "чай": 180.6}
assert price_with_tax({}) == {}
Задание 4 Заполнить таблицу

Что получится?

[0, 1, 4]{0, 1}{0: 0, 1: 1}генератор['чёт', 'нечет', 'чёт']
[x * x for x in range(3)]
{x % 2 for x in range(5)}
{x: x for x in range(2)}
(x for x in range(3))
['чёт' if x % 2 == 0 else 'нечет' for x in range(3)]
Отметьте ячейку — «+», пустая — «−».
Задание 5 Один вариант ответа

Почему sum(x * x for x in range(10**7)) лучше, чем sum([x * x for x in range(10**7)])?

Войдите, чтобы отмечать пройденные уроки.