Что такое генератор и чем он полезен?
- Как работает yield?
- Чем генератор отличается от обычной функции?
- Что такое yield from?
Генератор — функция с yield: отдаёт значения по одному и замирает между ними, сохраняя состояние.
- Ленивый: следующее значение вычисляется только по запросу
- Память O(1) вместо целого списка — можно обрабатывать огромные и бесконечные потоки
А ещё Генератор проходится один раз; второй проход ничего не даст
Подробно
Если в теле функции есть yield, её вызов не выполняет код, а возвращает объект-генератор. Генератор — итератор: каждый next() выполняет тело до следующего yield, отдаёт значение и приостанавливается. Локальные переменные и место остановки сохраняются. Когда функция заканчивается, генератор бросает StopIteration, и цикл for завершается.
Зачем:
- память — читать файл на 10 ГБ построчно, не загружая его целиком;
- ленивость — значения считаются только если нужны: можно взять первые 10 из бесконечной последовательности;
- конвейеры — генераторы удобно соединять в цепочку: прочитать → отфильтровать → преобразовать.
yield from other отдаёт все значения из другого итерируемого объекта — удобно для рекурсии и делегирования.
Ограничения: генератор исчерпывается после одного прохода; у него нет len() и доступа по индексу.
Пример
def read_lines(path):
with open(path, encoding="utf-8") as f:
for line in f:
yield line.rstrip("\n")
def numbers():
n = 0
while True: # бесконечный генератор
yield n
n += 1
from itertools import islice
list(islice(numbers(), 5)) # [0, 1, 2, 3, 4]
def flatten(items):
for x in items:
if isinstance(x, list):
yield from flatten(x)
else:
yield xЧто хотят услышать
- Механика
yield: пауза и сохранение состояния. - Ленивость и экономия памяти с практическим примером.
- Генератор — итератор, исчерпывается за один проход.
- Знание
yield fromи генераторных выражений — плюс.
Частые ошибки
- Пройти генератор второй раз и удивиться пустому результату.
- Считать, что вызов функции с
yieldсразу выполняет её код.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗Функция с yield, которая сразу вычисляет все значения и отдаёт их списком
- ✓Функция с yield, отдающая значения лениво по одному и хранящая состояние между ними
- ✗Генератор можно обойти сколько угодно раз
- ✗Генераторы не подходят для бесконечных последовательностей
Что спросят дальше
Разбор темы
- Итераторы, генераторы и itertools
Протокол итерации, генераторы и генераторные выражения, срезы, send и yield from, ленивые инструменты itertools.
Связанные вопросы
- Как работают async и await? Junior
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.