Встречается на 30% собеседований по Python

Что такое итератор

Итератор (iterator) — это объект, который представляет поток данных и возвращает элементы по одному за раз. Повторный вызов метода __next__() (или встроенной функции next()) возвращает следующий элемент потока, а когда элементы заканчиваются, выбрасывается исключение StopIteration. После этого итератор считается исчерпанным, и все последующие вызовы __next__() снова генерируют StopIteration. Итератор также обязан иметь метод __iter__, который возвращает сам объект итератора, поэтому любой итератор является итерируемым объектом и может использоваться в конструкциях, ожидающих итерируемые объекты, например в цикле for.

Как это работает

Итератор реализует два ключевых метода:

  • __next__() — возвращает следующий элемент последовательности. Если элементов больше нет, выбрасывает StopIteration.
  • __iter__() — возвращает self. Это делает итератор итерируемым, позволяя использовать его в for и других местах, где ожидается итерируемый объект.

В Python итераторы формально определяются абстрактным классом collections.abc.Iterator, который наследуется от Iterable. Класс Iterator требует реализации __next__ и предоставляет __iter__ по умолчанию. Также через __subclasshook__ проверяется наличие обоих методов у класса, что позволяет использовать isinstance(obj, Iterator) для проверки.

Пример

Создадим простой итератор, который возвращает квадраты чисел от 0 до n:

python
class SquaresIterator:
    def __init__(self, n):
        self.n = n
        self.i = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.i >= self.n:
            raise StopIteration
        result = self.i ** 2
        self.i += 1
        return result

# Использование
squares = SquaresIterator(5)
for x in squares:
    print(x)  # Выведет 0, 1, 4, 9, 16

Здесь __next__ возвращает квадрат текущего индекса и увеличивает его. Когда индекс достигает n, выбрасывается StopIteration, сигнализируя о конце итерации.

Подводные камни

  • Исчерпание: итератор можно использовать только один раз. После того как он выбросил StopIteration, он становится бесполезным. Чтобы пройтись по данным снова, нужно создать новый итератор.
  • Итератор и итерируемый объект: не путайте эти понятия. Итерируемый объект (например, список) имеет метод __iter__, который возвращает итератор. Сам список не является итератором, так как у него нет __next__. Итератор же всегда является итерируемым.
  • Бесконечные итераторы: итератор может не иметь конца (например, itertools.count). В таких случаях нужно явно ограничивать количество итераций, иначе цикл for будет бесконечным.
  • Реализация __iter__: если вы пишете свой класс-итератор, обязательно возвращайте self из __iter__. Если вернуть другой объект, это может привести к неожиданному поведению.

Когда использовать

Итераторы лежат в основе многих конструкций Python: циклы for, генераторы, функции map, filter, zip и другие. Понимание итераторов необходимо для работы с большими данными, так как они позволяют обрабатывать элементы по одному, не загружая всю последовательность в память. Также итераторы используются при создании пользовательских коллекций, которые должны поддерживать перебор.

Коротко

  • Итератор — объект с методами __next__ и __iter__, возвращающий элементы по одному и выбрасывающий StopIteration в конце.
  • Любой итератор является итерируемым, но не наоборот.
  • Итератор одноразовый: после исчерпания его нельзя переиспользовать.
  • Итераторы позволяют эффективно работать с потоками данных, не загружая их целиком в память.
как отвечать на вопрос
пример собеседования
фреймворки на собеседовании
типичные вопросы junior
интервью вопросы и ответы