Ответ
Протокол итератора в Python — это механизм, который позволяет объектам быть итерируемыми, то есть перебираемыми в цикле for
. Протокол состоит из двух частей и двух соответствующих методов:
-
Итерируемый объект (Iterable): Любой объект, у которого можно получить итератор. Он должен реализовывать метод
__iter__()
.__iter__()
: Возвращает объект-итератор. Примеры итерируемых объектов: списки, строки, словари, файлы.
-
Итератор (Iterator): Объект, который отслеживает состояние и производит следующее значение в последовательности. Он должен реализовывать два метода:
__iter__()
: Возвращает сам себя (return self
). Это позволяет использовать итераторы там, где ожидаются итерируемые объекты.__next__()
: Возвращает следующий элемент. Когда элементы заканчиваются, вызывает исключениеStopIteration
.
Цикл for
неявно использует этот протокол: сначала он вызывает __iter__()
у объекта, чтобы получить итератор, а затем многократно вызывает __next__()
у этого итератора, пока не будет поймано исключение StopIteration
.
Пример реализации своего итератора:
class EvenNumbers:
"""Итератор, который генерирует четные числа до указанного предела."""
def __init__(self, limit):
self.limit = limit
self.current = 0
def __iter__(self):
# Возвращает сам объект-итератор
return self
def __next__(self):
if self.current < self.limit:
value = self.current
self.current += 2
return value
else:
# Сигнал о завершении итерации
raise StopIteration
# Использование
print("Использование класса-итератора:")
for number in EvenNumbers(10):
print(number) # Выведет 0, 2, 4, 6, 8
Более простой способ — генераторы
Функции-генераторы с ключевым словом yield
автоматически создают объект, реализующий протокол итератора, что делает код значительно короче и чище.
def even_numbers_generator(limit):
"""Генератор, делающий то же самое, что и класс выше."""
current = 0
while current < limit:
yield current
current += 2
# Использование генератора
print("nИспользование функции-генератора:")
for number in even_numbers_generator(10):
print(number) # Выведет 0, 2, 4, 6, 8