Генераторы, iter() и идентичность

Генераторы, iter() и идентичность

@python_quiz

Разберем этот квиз

Коротко: в коде используется генераторное выражение, и ключевой момент — генератор уже является итератором, поэтому вызов iter() возвращает тот же объект. Также генератор одноразовый: если в нём нет элементов, попытка получить из него что-либо сразу приведёт к StopIteration и список окажется пустым.

Исходный код

python

Разберём по шагам, что тут происходит.

Пошаговый разбор

  • g = (x for x in []) — создаётся генератор (generator object). Генераторное выражение всегда возвращает объект-генератор.
  • Генератор реализует протокол итератора: у него есть метод __iter__(), который возвращает сам объект. Поэтому iter(g) возвращает g.
  • it1 = iter(g); it2 = iter(it1) — оба присваивания дают один и тот же объект. Проверка it1 is it2 вернёт True.
  • Генератор перебирает элементы по требованию. В данном случае он создан из пустого итерируемого, поэтому при первой попытке получить элемент он сразу бросит StopIteration.
  • list(it2) пытается пройти по оставшимся элементам генератора и собрать их в список. Поскольку элементов нет, результат — пустой список [].

Итого: выражение напечатает True и пустой список.

Демонстрация в коде

Оригинальный пример:

python

Пример с ненулевым генератором:

python

Контраст: список (итерируемый, но не итератор)

python

Контраст: пользовательский итерируемый класс, возвращающий новый итератор:

python

Выводы и полезные наблюдения

  • Генератор (generator object) — это итератор: вызов iter(generator) возвращает сам генератор.
  • Для генераторов it1 is iter(it1) будет True.
  • Генераторы одноразовые: после полного обхода дальнейшие попытки чтения вернут StopIteration, и list(…) вернёт пустой список.
  • Для обычных итерируемых объектов (список, строка, пользовательские контейнеры) вызов iter() обычно создаёт новый независимый итератор — поэтому identity будет False.

Такое поведение важно помнить при проектировании кода: если нужен многократный проход по данным — используйте коллекции или создавайте новый итератор заново; если нужен ленивый одноразовый поток — подойдёт генератор.

Report Page