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

Как происходит итерация?

1.0 Junior🔥 151 комментариев
#Python Core

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

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

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

Как происходит итерация в Python

Итерация — это процесс последовательного обхода элементов контейнера. Понимание механики итерации критично для написания эффективного Python кода и создания собственных итерируемых объектов.

Теория: Iterables, Iterators и Protocol

В Python есть три ключевых концепции:

1. Iterable (Итерируемый объект)

Любой объект, который имеет метод __iter__(), возвращающий итератор:

my_list = [1, 2, 3]
print(hasattr(my_list, '__iter__'))  # True

# Вызов __iter__() создаёт итератор
iterator = iter(my_list)
print(type(iterator))  # <class 'list_iterator'>

2. Iterator (Итератор)

Объект с двумя методами: __iter__() (возвращает сам себя) и __next__() (возвращает следующий элемент):

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

print(next(my_iter))  # 1
print(next(my_iter))  # 2
print(next(my_iter))  # 3
print(next(my_iter))  # StopIteration ← исключение

Практический пример: что происходит в цикле

# Когда ты пишешь:
for item in [1, 2, 3]:
    print(item)

# Python делает РОВНО ЭТО:
my_iter = iter([1, 2, 3])  # Вызов __iter__()
while True:
    try:
        item = next(my_iter)  # Вызов __next__()
        print(item)
    except StopIteration:
        break  # Выход из цикла

Создание собственного итератора

Способ 1: Класс с iter() и next()

class CountUp:
    def __init__(self, max):
        self.max = max
        self.current = 0
    
    def __iter__(self):
        return self  # Возвращаем сам объект как итератор
    
    def __next__(self):
        if self.current < self.max:
            self.current += 1
            return self.current
        else:
            raise StopIteration  # Сигнал конца итерации

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

Способ 2: Генератор (самый Pythonic способ)

Генератор автоматически реализует протокол итератора:

def count_up(max):
    current = 0
    while current < max:
        current += 1
        yield current  # Приостанавливает и возвращает значение

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

# Генератор «ленивый» — создаёт значения по требованию
gen = count_up(3)
print(next(gen))  # 1
print(next(gen))  # 2
print(next(gen))  # 3

Разница между Iterables и Iterators

# Iterable — можешь вызвать iter() и получить итератор
my_list = [1, 2, 3]
iterator1 = iter(my_list)  # Каждый раз новый итератор
iterator2 = iter(my_list)
print(iterator1 is iterator2)  # False — разные объекты

# Iterator — одновременно итератор и итерируемый
my_iter = iter([1, 2, 3])
print(my_iter is iter(my_iter))  # True — всегда возвращает себя

# Важно: дважды итерировать список можно, но не итератор
data = [1, 2, 3]
for x in data:
    print(x)  # 1, 2, 3
for x in data:
    print(x)  # 1, 2, 3 — работает заново

my_iter = iter(data)
for x in my_iter:
    print(x)  # 1, 2, 3
for x in my_iter:
    pass  # Не печатает ничего — итератор уже исчерпан

Встроенные функции для итерации

enumerate() — получить индекс и значение:

for index, item in enumerate(['a', 'b', 'c'], start=1):
    print(f"{index}: {item}")  # 1: a, 2: b, 3: c

zip() — объединить несколько итерируемых:

names = ['Alice', 'Bob']
ages = [25, 30]

for name, age in zip(names, ages):
    print(f"{name}: {age}")  # Alice: 25, Bob: 30

map() и filter() — функциональное программирование:

numbers = [1, 2, 3, 4, 5]

# map — преобразование каждого элемента
squared = map(lambda x: x ** 2, numbers)
print(list(squared))  # [1, 4, 9, 16, 25]

# filter — выбор элементов по условию
evens = filter(lambda x: x % 2 == 0, numbers)
print(list(evens))  # [2, 4]

Важные особенности

Генераторы — ленивые вычисления:

import sys

# Список хранит ВСЕ значения в памяти
big_list = [x for x in range(1_000_000)]
print(sys.getsizeof(big_list))  # ~8 млн байт

# Генератор создаёт значения по требованию
big_gen = (x for x in range(1_000_000))
print(sys.getsizeof(big_gen))  # ~128 байт

# Для итерации одинаково работает
for num in big_gen:
    if num > 5:
        break

StopIteration в Python 3.7+:

def my_gen():
    yield 1
    yield 2
    return 3  # Значение возвращается в StopIteration.value

gen = my_gen()
print(next(gen))  # 1
print(next(gen))  # 2
try:
    next(gen)  # Вызывает StopIteration
except StopIteration as e:
    print(e.value)  # 3

Вывод

Итерация в Python — это протокол, основанный на методах __iter__() и __next__(). Это позволяет создавать мощные, ленивые и эффективные по памяти конструкции. Генераторы — идеальный способ реализации итераторов в большинстве случаев.

Как происходит итерация? | PrepBro