Sobes.tech
Назад к вопросам
Junior — Middle
57

Каким образом следует реализовать методы внутри собственного класса для обеспечения его возможности итерирования?

Ответ от нейросети

sobes.tech AI

Что хотят услышать интервьюеры:

Чтобы объект собственного класса можно было использовать в for, он должен реализовывать итераторный протокол: возвращать итератор через __iter__() и выдавать элементы через __next__(). Если нужен только сам объект-коллекция, достаточно, чтобы __iter__() возвращал итератор по внутренним данным. Для простых случаев часто проще делегировать итерирование встроенному контейнеру, например списку.

Определение:

Итерируемым считается объект, по которому можно пройтись циклом for. В Python это обычно достигается двумя способами: либо класс сам является итератором и реализует __iter__() и __next__(), либо __iter__() возвращает отдельный итератор, например iter(self.items).
__iter__() должен вернуть объект, который умеет выдавать элементы по одному. __next__() должен возвращать следующий элемент и выбрасывать StopIteration, когда элементы закончились.

Пример использования:

class Numbers:
    def __init__(self, start, end):
        self.start = start
        self.end = end

    def __iter__(self):
        self.current = self.start
        return self

    def __next__(self):
        if self.current > self.end:
            raise StopIteration
        value = self.current
        self.current += 1
        return value


nums = Numbers(1, 3)

for n in nums:
    print(n)

Пояснение кода:

  1. В __iter__() объект подготавливается к обходу: счётчик current устанавливается в начало диапазона.
  2. __iter__() возвращает self, значит сам объект выступает итератором.
  3. Каждый вызов __next__() возвращает текущее значение и сдвигает счётчик дальше.
  4. Когда значения заканчиваются, __next__() выбрасывает StopIteration, и цикл for завершается.

Если нужно, чтобы класс был просто итерируемым, но не итератором, можно сделать так:

class Numbers:
    def __init__(self, values):
        self.values = values

    def __iter__(self):
        return iter(self.values)

Здесь код не нужно писать вручную для __next__(), потому что итерирование делегируется списку values.

Ключевые моменты:

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