Короткий ответ Класс-итератор реализует __iter__ (обычно возвращает self) и __next__ (вычисляет и возвращает следующее значение при каждом вызове); об окончании последовательности он сигнализирует, возбуждая исключение StopIteration внутри __next__, которое цикл for автоматически перехватывает и завершает итерацию. Как это работает подробнее Протокол итератора требует двух методов: __iter__(self), возвращающий объект-итератор (часто self, если класс одновременно итерируемый и итератор), и __next__(self), возвращающий очередное значение или возбуждающий StopIteration, когда значений больше нет. Конструкция for x in obj: под капотом вызывает iter(obj) один раз, затем повторяет next(it) в цикле, автоматически останавливаясь при перехвате StopIteration без вывода ошибки пользователю. Пример кода Что использовать на практике Практика. Такой подход используют, когда нужен контроль над состоянием итерации (например, итератор с ленивой подгрузкой страниц из API или БД), а не просто требуется перебрать готовую коллекц