Что такое list comprehension?
List comprehension — компактный способ создать список из другой последовательности:
squares = [x ** 2 for x in range(10)]
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Эквивалент через цикл:
squares = []
for x in range(10):
squares.append(x ** 2)
Comprehension короче, читается слева направо и обычно быстрее.
Базовый синтаксис
[выражение for переменная in итерируемое]
names = ["alice", "bob", "carol"]
upper = [name.upper() for name in names]
# ['ALICE', 'BOB', 'CAROL']
С фильтрацией (if)
[выражение for переменная in итерируемое if условие]
numbers = range(20)
evens = [n for n in numbers if n % 2 == 0]
# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
If-else в выражении
Тернарный оператор стоит до for:
result = ["чётное" if n % 2 == 0 else "нечётное" for n in range(5)]
# ['чётное', 'нечётное', 'чётное', 'нечётное', 'чётное']
Вложенные comprehension
Для работы с матрицами или вложенными списками:
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
# Транспонирование
transposed = [[row[i] for row in matrix] for i in range(3)]
# [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
# Плоский список (flatten)
flat = [item for row in matrix for item in row]
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
Dict comprehension
words = ["apple", "banana", "cherry"]
lengths = {word: len(word) for word in words}
# {'apple': 5, 'banana': 6, 'cherry': 6}
Инвертирование словаря:
original = {"a": 1, "b": 2, "c": 3}
inverted = {v: k for k, v in original.items()}
# {1: 'a', 2: 'b', 3: 'c'}
Set comprehension
sentence = "привет мир привет python"
unique_words = {word for word in sentence.split()}
# {'привет', 'мир', 'python'}
Генераторные выражения
Синтаксис как у list comprehension, но в скобках (). Не создаёт список сразу — вычисляет элементы по одному:
gen = (x ** 2 for x in range(1_000_000))
print(next(gen)) # 0
print(next(gen)) # 1
Экономят память при работе с большими данными:
# Сумма квадратов без создания промежуточного списка
total = sum(x ** 2 for x in range(1_000_000))
Когда использовать comprehension, а когда цикл
✅ Comprehension — когда:
- Создаёте новый список/словарь/множество
- Логика простая, умещается в одну строку
- Нужна фильтрация
❌ Цикл — когда:
- Побочные эффекты (print, запись в файл)
- Сложная многошаговая логика
- Нужен break/continue
# ❌ Плохо — comprehension для побочного эффекта
[print(x) for x in range(10)]
# ✅ Хорошо — цикл для побочного эффекта
for x in range(10):
print(x)
Производительность
List comprehension обычно быстрее явного цикла с append():
import timeit
# Цикл: ~0.5 сек
timeit.timeit("r = []\nfor x in range(1000): r.append(x**2)", number=10000)
# Comprehension: ~0.3 сек
timeit.timeit("[x**2 for x in range(1000)]", number=10000)
Практические паттерны
Фильтрация None
data = [1, None, 3, None, 5]
clean = [x for x in data if x is not None]
# [1, 3, 5]
Уникальные элементы с сохранением порядка
seen = set()
unique = [x for x in [3, 1, 2, 1, 3, 4] if not (x in seen or seen.add(x))]
# [3, 1, 2, 4]
Разбивка на части (chunks)
lst = list(range(10))
chunks = [lst[i:i+3] for i in range(0, len(lst), 3)]
# [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]
Декартово произведение
colors = ["red", "green"]
sizes = ["S", "M", "L"]
variants = [(c, s) for c in colors for s in sizes]
# [('red', 'S'), ('red', 'M'), ('red', 'L'), ('green', 'S'), ...]
Итог
| Тип | Синтаксис | Результат |
|---|---|---|
| List | [expr for x in it] | list |
| Dict | {k: v for x in it} | dict |
| Set | {expr for x in it} | set |
| Generator | (expr for x in it) | generator |
Comprehension — один из самых питоничных инструментов Python. Практикуйте их в задачах тренажёра!