Как работает ключевое слово yield в Python
yieldасинхронностьгенераторыитераторыфункции
Что проверяют
Понимаете ли вы, что функция превращается в генератор, и знаете ли, зачем это нужно кроме экономии памяти.
Как отвечать
yield превращает функцию в генератор. Вызов такой функции не выполняет её тело, а возвращает объект генератора. Тело начинает выполняться при первом запросе значения и приостанавливается на yield, сохраняя локальные переменные и точку остановки. Следующий запрос продолжает с того же места.
def numbers(n):
for i in range(n):
yield i * iЗачем это нужно:
- ленивость: значения вычисляются по мере запроса. Можно обрабатывать файл на десять гигабайт, не держа его в памяти;
- бесконечные последовательности: генератор может не иметь конца, а потребитель сам решит, сколько взять;
- конвейеры: генераторы соединяются друг с другом, и данные проходят через цепочку по одному элементу, без промежуточных списков.
Что стоит знать дополнительно:
yield fromделегирует другому генератору, пробрасывая и значения, и отправляемые внутрь данные. Заменяет ручной цикл с перебором;returnвнутри генератора завершает его, а возвращённое значение кладётся в исключение остановки. Обычным способом его не получить;- генератор двусторонний: метод отправки передаёт значение обратно в точку приостановки, есть также возбуждение исключения внутри и закрытие. На этом механизме построен декоратор контекстного менеджера, и из него же исторически выросли корутины.
Главные ловушки:
- генератор одноразовый. Прошли по нему один раз, второй проход не даст ничего. Это регулярно ломает код, где результат перебирают дважды;
- нельзя взять длину и обратиться по индексу;
- отложенность меняет момент ошибки: исключение возникнет не при вызове функции, а при получении значения, иногда далеко от места вызова.
Где спотыкаются
Ждут, что тело функции выполнится при вызове.
Перебирают генератор дважды и получают пустой результат.
Вызывают len() на генераторе.
Не знают про yield from и пишут ручные циклы делегирования.