yield, генераторные выражения, протокол итератора (__iter__, __next__) — продвинутый Python, который спрашивают у кандидатов на middle+. Генераторы экономят память при обработке больших данных. На собеседовании просят объяснить ленивое вычисление, написать генератор или показать разницу между списком и генератором.
`range(n)` генерирует числа от 0 до `n - 1`. Для `n = 3` это 0, 1, 2, а квадраты — 0, 1, 4. `list(...)` собирает все значения, которые отдаёт `yield`.
Подробный разбор →List comprehension создаёт список всех валидных строк сразу, что может быть дорого по памяти. Генератор с `yield` выдаёт элементы по одному, поэтому вы можете сразу передавать их в следующий шаг пайплайна (`for row in valid(rows): ...`) без хранения всего набора. Это типичный приём для экономии памяти на больших логах.
Подробный разбор →Список, строка и set — iterable: по ним можно итерироваться в `for`, но они не являются iterator (у них нет текущего состояния «где мы»). Вызов `iter([1, 2])` создаёт iterator, у которого можно вызывать `next(...)`.
Подробный разбор →Два вызова `next(it)` последовательно забрали 1 и 2. Цикл `for` продолжит чтение того же iterator и получит только оставшееся значение 3. Это удобно, но может стать багом, если вы не ожидали, что iterator разделяется между `next()` и `for`.
Подробный разбор →Вызов `next(g)` забирает первый `yield` (1) и переносит исполнение генератора дальше. Затем `list(g)` забирает оставшиеся значения, которые ещё не были выданы: 2 и 3. Поэтому `rest` равно `[2, 3]`.
Подробный разбор →В приложении — таймер, прогресс, стрики и 1700+ вопросов по всем темам.
Тренировать Python в Telegram