> Что должно присутствовать у объекта, чтобы он был итератором в Python (Python)
Уровень: senior · Роль: backend · Категория: Технические вопросы
Компании: Сбер
Стек: Python
> Пример ответа
Короткий ответ
Итератор в Python - это объект, который реализует протокол итератора: метод __next__(), возвращающий следующий элемент или бросающий StopIteration, и метод __iter__(), возвращающий сам объект. Наличие __iter__() делает итератор одновременно итерируемым объектом. Формально достаточно реализовать __next__(), но без __iter__() объект не будет работать в циклах for и других конструкциях, ожидающих итерируемый объект.
Подробное объяснение
Протокол итератора в Python состоит из двух методов:
__iter__(self)- возвращает сам итератор. Этот метод делает объект итерируемым, позволяя использовать его вfor,sum(),list()и т.д.__next__(self)- возвращает следующий элемент последовательности. Когда элементы закончились, метод должен бросить исключениеStopIteration.
Важные нюансы:
- Итератор - это одноразовый объект: после исчерпания он не может быть перезапущен. Повторный вызов
iter()на итераторе вернёт тот же самый объект, а не новый. - Итератор отличается от итерируемого объекта: итерируемый объект (например, список) реализует только
__iter__(), возвращая новый итератор при каждом вызове. - Встроенная функция
iter()проверяет наличие__iter__(), аnext()- наличие__next__(). - Для проверки, является ли объект итератором, можно использовать
isinstance(obj, collections.abc.Iterator)- этот ABC проверяет наличие обоих методов. - С версии Python 3.7
__next__можно реализовать как__next__ = lambda self: ..., но это скорее антипаттерн.
На практике
В реальном коде итераторы редко реализуют вручную - чаще используют генераторы (функции с yield), которые автоматически создают итератор. Однако понимание протокола необходимо для:
- Создания кастомных потоковых или ленивых последовательностей.
- Реализации бесконечных последовательностей (например, генерация чисел Фибоначчи без ограничения).
- Понимания работы
zip,map,filterи других функций, возвращающих итераторы. - Написания собственных классов, которые должны работать в циклах.
Типичный паттерн - класс, который является одновременно итерируемым и итератором (реализует оба метода), но это допустимо только если объект одноразовый. Для многоразового использования нужно разделять: контейнер реализует __iter__, а отдельный класс - итератор.
Пример кода
PYTHONclass Countdown:"""Итератор, который считает от n до 1."""def __init__(self, start):self.current = startdef __iter__(self):return selfdef __next__(self):if self.current <= 0:raise StopIterationvalue = self.currentself.current -= 1return value# Использованиеfor num in Countdown(3):print(num) # 3, 2, 1# Проверка через ABCfrom collections.abc import Iteratorprint(isinstance(Countdown(3), Iterator)) # True# Одноразовостьcd = Countdown(2)print(list(cd)) # [2, 1]print(list(cd)) # [] - итератор исчерпан
Как отвечать на собеседовании
Начните с формального определения: два метода, их сигнатуры и поведение. Затем покажите понимание различий между итератором и итерируемым объектом - это частый источник путаницы. Упомяните StopIteration как механизм завершения. Если спросят про генераторы, скажите, что они реализуют тот же протокол автоматически. Хорошо добавить пример из практики: когда вы реализовывали итератор вручную и почему генератор не подходил (например, нужен был объект с состоянием и дополнительными методами).
Что проверяет интервьюер
- Понимание протокола итератора, а не заученное определение.
- Умение различать итератор и итерируемый объект.
- Знание поведения
StopIterationи одноразовости итераторов. - Понимание, как работает цикл
forпод капотом: вызываетiter()и затемnext()доStopIteration. - Осведомлённость о
collections.abc.Iteratorи встроенных функцияхiter()/next().
Типичные ошибки
- Утверждение, что достаточно только
__next__()- без__iter__()объект не будет работать вfor. - Путаница между
__iter__и__next__: иногда говорят, что__iter__возвращает следующий элемент. - Забывают про
StopIterationили бросаютIndexErrorвместо него. - Не учитывают одноразовость: пытаются использовать один и тот же итератор дважды.
- Считают, что генераторы - это не итераторы, хотя они реализуют тот же протокол.
- Реализуют
__next__без изменения внутреннего состояния - получается бесконечный цикл.
> Похожие задачи по backend
Как вывести в одном датафрейме результаты по студентам с баллами по математике и биологии ниже 80
Как параллелить выполнение функции в Python
Какие типы данных существуют в Python
Что происходит с автонастройкой перед сохранением в Django
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью