Что должно присутствовать у объекта, чтобы он был итератором в Python
Что проверяют
Различаете ли вы итерируемый объект и итератор. Для инженера данных это не теория: именно на этом различии ломаются пайплайны, где набор читается потоком, а проходов по нему больше одного.
Как отвечать
Итератор это объект с двумя методами. __next__ отдаёт следующий элемент и возбуждает StopIteration, когда элементы кончились. __iter__ возвращает сам объект, то есть return self. Второй метод обязателен потому, что цикл for сначала зовёт iter() для любого объекта: без него итератор нельзя подставить в цикл напрямую.
Итерируемый объект это объект, у которого есть __iter__, возвращающий новый итератор. Список итерируемый, но не итератор: у него нет __next__, зато iter(lst) каждый раз создаёт свежий обходчик, поэтому по списку можно пройти дважды. Есть и старый протокол: объект с __getitem__, принимающим целые индексы с нуля, тоже работает в for.
Ещё два правила: исчерпанный итератор обязан и дальше возбуждать StopIteration, а не начинать сначала, и проще всего получить итератор генератором, yield даёт оба метода бесплатно.
it = iter([1, 2])
next(it), next(it) # 1, 2
next(it) # StopIterationГде спотыкаются
Пишут __iter__ с return self в классе, который на самом деле коллекция. Объект становится одноразовым: второй проход по нему пустой, и цикл обучения молча идёт по нулю примеров. Коллекция обязана возвращать новый итератор при каждом вызове.
Забывают про StopIteration и возвращают None в конце данных. Цикл не заканчивается никогда, а попытка собрать такой объект в список съедает память.
Считают, что поточный набор данных можно просто раздать по процессам. Итератор хранит состояние и не делится сам: при чтении несколькими рабочими процессами каждый получает свою копию источника и выдаёт те же самые записи, пока поток не разделён по номеру процесса.