Вы фильтруете большой поток строк rows. Почему генератор def valid(rows): for row in rows: if is_valid(row): yield row часто экономнее по памяти, чем выражение [row for row in rows if is_valid(row)]?

Ayield сохраняет промежуточные строки во временный файл на диске, освобождая оперативную память.
BГенератор списка нельзя использовать в цикле for, в отличие от функции с yield.
CГенератор отдаёт строки по одной и не хранит весь набор в памяти, а сразу передаёт следующему шагу обработки.
DФункция-генератор гарантированно работает быстрее списка в любом случае, даже при многократном обходе данных.
Правильный ответ. Генератор лениво выдаёт элементы по одному, не материализуя весь набор в памяти.

Разбор

Когда valid(rows) написана через yield, она запускает обработку одной строки за раз: вернула значение, остановилась, ждёт следующего next(). Список же сначала собирает все строки целиком в памяти, а затем уже отдаёт их следующему шагу. На больших потоках это и даёт экономию памяти, особенно при чтении из файла или БД. Никакого автоматического сброса на диск yield не делает, и по скорости генератор не всегда выигрывает: если данные обходятся несколько раз, заранее построенный список может быть выгоднее.

Проверь себя · 1/3разбор после ответа
Есть функция def f(x): print(x); return x. Создали g = (f(x) for x in [1, 2, 3]). Сразу после создания g, до любой итерации, сколько раз выполнится print(x)?
Тренировать Python в Telegram

Ещё вопросы по теме «Итераторы и генераторы»