← Назад к вопросам

Как взаимосвязаны цикл for и метод next в итераторе?

2.0 Middle🔥 141 комментариев
#Soft Skills

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

For Loop и next(): Взаимосвязь Итераторов

Это фундаментальный вопрос о том, как работают итерторы в Python. Цикл for на самом деле — это синтаксический сахар над методом next().

Как for работает под капотом

Когда ты пишешь:

for item in iterable:
    print(item)

Python делает следующее:

# Эквивалент работы for цикла
iterator = iter(iterable)  # Получаем итератор

while True:
    try:
        item = next(iterator)  # Вызываем next()
        print(item)
    except StopIteration:
        break  # Выход из цикла при StopIteration

Понимание iter() и next()

iter() — встроенная функция, которая преобразует объект в итератор:

my_list = [1, 2, 3]
iterator = iter(my_list)

print(next(iterator))  # 1
print(next(iterator))  # 2
print(next(iterator))  # 3
print(next(iterator))  # StopIteration

Протокол итератора

Объект считается итератором, если реализует два метода:

class MyIterator:
    def __init__(self, max_value):
        self.current = 0
        self.max = max_value
    
    def __iter__(self):
        """Возвращает сам итератор"""
        return self
    
    def __next__(self):
        """Возвращает следующий элемент или выбрасывает StopIteration"""
        if self.current < self.max:
            self.current += 1
            return self.current
        else:
            raise StopIteration

# Использование
for num in MyIterator(3):
    print(num)  # 1, 2, 3

# Эквивалентно
iterator = MyIterator(3)
print(next(iterator))  # 1
print(next(iterator))  # 2
print(next(iterator))  # 3
try:
    print(next(iterator))  # StopIteration
except StopIteration:
    print("Итератор исчерпан")

Различие между итерируемыми и итераторами

Итерируемый объект (iterable) — имеет метод __iter__():

# Это итерируемые объекты
list_obj = [1, 2, 3]          # Список
string_obj = "hello"          # Строка
dict_obj = {"a": 1}           # Словарь
range_obj = range(5)          # Range

print(hasattr(list_obj, "__iter__"))  # True

Итератор — имеет методы __iter__() и __next__():

list_iterator = iter([1, 2, 3])

print(hasattr(list_iterator, "__iter__"))   # True
print(hasattr(list_iterator, "__next__"))   # True

# Итератор сам по себе итерируем
for item in list_iterator:
    print(item)

Практический пример: Custom Iterator

class RangeIterator:
    """Аналог встроенного range()"""
    
    def __init__(self, start, end):
        self.current = start
        self.end = end
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.current < self.end:
            value = self.current
            self.current += 1
            return value
        else:
            raise StopIteration

# Использование в for цикле
for i in RangeIterator(1, 4):
    print(i)  # 1, 2, 3

# Явное использование next()
my_range = RangeIterator(1, 4)
print(next(my_range))  # 1
print(next(my_range))  # 2
print(next(my_range))  # 3

Генераторы: Синтаксический сахар для итераторов

Генераторы — это простой способ создания итераторов с помощью yield:

# Обычный итератор
class CountIterator:
    def __init__(self, n):
        self.n = n
        self.i = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.i < self.n:
            self.i += 1
            return self.i
        else:
            raise StopIteration

# Генератор (более простой способ)
def count_generator(n):
    i = 0
    while i < n:
        i += 1
        yield i

# Оба работают одинаково
for num in CountIterator(3):
    print(num)  # 1, 2, 3

for num in count_generator(3):
    print(num)  # 1, 2, 3

Бесконечные итераторы

class InfiniteCounter:
    def __init__(self, start=0):
        self.current = start
    
    def __iter__(self):
        return self
    
    def __next__(self):
        value = self.current
        self.current += 1
        return value

# Использование с break
for i in InfiniteCounter():
    print(i)
    if i == 5:
        break  # 0, 1, 2, 3, 4, 5

Встроенные утилиты для работы с итераторами

from itertools import count, cycle, repeat, islice

# count() — бесконечный счётчик
for num in islice(count(1), 5):
    print(num)  # 1, 2, 3, 4, 5

# cycle() — циклически повторяет элементы
for item in islice(cycle([1, 2, 3]), 7):
    print(item)  # 1, 2, 3, 1, 2, 3, 1

# repeat() — повторяет значение
for item in islice(repeat("a"), 3):
    print(item)  # a, a, a

# zip() работает с итераторами
for a, b in zip([1, 2], ["a", "b"]):
    print(a, b)  # 1 a, 2 b

Состояние итератора

Важно понимать, что итератор имеет состояние:

my_list = [1, 2, 3]
iterator = iter(my_list)

print(next(iterator))  # 1 — итератор изменил своё состояние
print(next(iterator))  # 2

# Новый итератор начинает заново
new_iterator = iter(my_list)
print(next(new_iterator))  # 1

Lazy Evaluation

Итераторы поддерживают ленивое вычисление — элементы генерируются по требованию:

def lazy_range(n):
    """Элементы создаются только при вызове next()"""
    for i in range(n):
        print(f"Generating {i}")
        yield i

for num in lazy_range(3):
    print(f"Processing {num}")
# Output:
# Generating 0
# Processing 0
# Generating 1
# Processing 1
# Generating 2
# Processing 2

Заключение

  • for цикл использует iter() и next() под капотом
  • iter() возвращает итератор из итерируемого объекта
  • next() возвращает следующий элемент
  • StopIteration сигнализирует о конце
  • Генераторы — простой способ создания итераторов
  • Ленивое вычисление экономит память для больших последовательностей

Понимание этого механизма критично для написания эффективного Python-кода.

Как взаимосвязаны цикл for и метод next в итераторе? | PrepBro