Вычисления «по требованию» или ленивые расчёты стали популярны с ростом объёмов обрабатываемых данных. В Python такие механизмы были реализованы в стандартной библиотеке через генераторы и итераторы, позже — через функцию itertools и классы, способные отдавать по одному элементу по запросу, избегая хранения всех данных в памяти сразу.
Обычное построение коллекций требует загрузить в память весь результат. Если объём большой — программа может «упасть» или работать очень медленно. Важно уметь обрабатывать потоки данных — например, файлы на множество гигабайт или результаты запросов к API.
Ленивые вычисления позволяют получать элементы по мере необходимости. В Python это облегчено использованием генераторов, синтаксиса yield, выражений-генераторов, функций map, filter, zip, а также модулем itertools. Такой подход основан на протоколе итераторов.
Пример кода:
def huge_sequence(): for i in range(1, 10**9): yield i * i for val in huge_sequence(): if val > 100: break print(val)
Ключевые особенности:
Всегда ли генераторы в Python экономят память?
Ответ: Нет, только если данные реально не требуют промежуточного хранения между шагами. Некоторые конструкции, например list comprehensions, создают весь список сразу, а генераторы — только по запросу. Если промежуточные результаты всё равно нужны, экономия теряется.
Пример:
squares = (x**2 for x in range(10**8)) # лениво, экономно result = list(squares) # мгновенно съедает всю память
Верно ли, что map и filter всегда возвращают списки?
Нет, в Python 3 map и filter возвращают не список, а итератор (ленивый генератор), что экономит память и позволяет обрабатывать данные «на лету».
Можно ли многократно итерироваться по генератору?
Нет, генератор «выгорает» после полного обхода. Если нужно повторное прохождение, стоит создавать новый генератор или использовать контейнер-коллекцию, содержимое которой можно многократно обходить.
Разработчик пытается обработать большой лог-файл, загружая его в память списком строк.
Плюсы:
Минусы:
Используется генератор — построчное чтение файла с обработкой каждой строки по мере получения.
Плюсы:
Минусы: