← Назад к вопросам
Что происходит при окончании перебора последовательности в итераторе Python?
3.0 Senior🔥 241 комментариев
#DevOps и инфраструктура#Django
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Окончание перебора в итераторе Python
Когда итератор достигает конца последовательности, он выбрасывает исключение StopIteration. Это сигнал для цикла for или другого потребителя, что элементов больше нет.
Механизм работы итераторов
Каждый итератор в Python должен реализовать два метода:
class CustomIterator:
def __iter__(self):
"""Возвращает сам итератор"""
return self
def __next__(self):
"""Возвращает следующий элемент или выбрасывает StopIteration"""
if self.has_next():
return self.get_next_value()
else:
raise StopIteration # Это конец итерации!
Практический пример
class CountUp:
def __init__(self, max_value):
self.max = max_value
self.current = 1
def __iter__(self):
return self
def __next__(self):
if self.current <= self.max:
value = self.current
self.current += 1
return value
else:
raise StopIteration
counter = CountUp(3)
print(next(counter)) # 1
print(next(counter)) # 2
print(next(counter)) # 3
print(next(counter)) # StopIteration!
Как цикл for обрабатывает StopIteration
Цикл for автоматически перехватывает это исключение:
for num in CountUp(3):
print(num)
# Что на самом деле происходит:
iterator = CountUp(3).__iter__()
while True:
try:
num = iterator.__next__()
print(num)
except StopIteration:
break # Цикл автоматически заканчивается
Явное использование next()
Если вызывать next() вручную после конца последовательности:
data = iter([1, 2, 3])
print(next(data)) # 1
print(next(data)) # 2
print(next(data)) # 3
print(next(data)) # StopIteration exception
Можно предоставить значение по умолчанию:
data = iter([1, 2, 3])
print(next(data, "No more")) # 1
print(next(data, "No more")) # 2
print(next(data, "No more")) # 3
print(next(data, "No more")) # No more вместо исключения
Встроенные итераторы Python
Все встроенные типы следуют этому протоколу:
it = iter([1, 2, 3])
print(next(it)) # 1
print(next(it)) # 2
print(next(it)) # 3
print(next(it)) # StopIteration
it = iter("ABC")
print(next(it)) # A
print(next(it)) # B
print(next(it)) # C
print(next(it)) # StopIteration
Генераторы и StopIteration
Генераторы тоже выбрасывают StopIteration, но это происходит автоматически:
def simple_generator():
yield 1
yield 2
yield 3
gen = simple_generator()
print(next(gen)) # 1
print(next(gen)) # 2
print(next(gen)) # 3
print(next(gen)) # StopIteration
Обработка StopIteration
Обычно не ловите вручную, но иногда нужно:
def get_first_element(iterable, default=None):
try:
return next(iter(iterable))
except StopIteration:
return default
print(get_first_element([1, 2, 3])) # 1
print(get_first_element([], default=42)) # 42
PEP 479: Изменения в Python 3.7+
Если внутри генератора выбросить StopIteration, она автоматически преобразуется в RuntimeError:
def bad_generator():
yield 1
raise StopIteration # В Python 3.7+ это RuntimeError!
def good_generator():
yield 1
return # Правильно
Ключевые моменты
- StopIteration — это нормальный сигнал завершения
- Цикл for автоматически его перехватывает
- next() с параметром безопаснее вручную
- Кастомные итераторы должны его выбрасывать
- Генераторы выбрасывают его автоматически
Это фундаментальная часть Python протокола итерирования.