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

Какие методы должен поддерживать итерируемый объект в Python?

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

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

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

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

Методы, которые должен поддерживать итерируемый объект

В Python существует четкое различие между итерируемыми объектами (iterable) и итераторами (iterator). Я часто работаю с обоими и знаю их полные контракты.

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

Итерируемый объект — это объект, который может быть использован в цикле for. Для этого класс должен реализовать метод __iter__.

Метод __iter__

Этот метод обязателен для итерируемого объекта и должен возвращать объект-итератор:

class SimpleIterable:
    def __init__(self, data):
        self.data = data
    
    def __iter__(self):
        # Должен возвращать объект, поддерживающий итератор протокол
        return iter(self.data)

# Использование
obj = SimpleIterable([1, 2, 3])
for item in obj:
    print(item)  # 1, 2, 3

Метод __iter__ может возвращать:

  • Другой объект (чаще всего итератор)
  • Сам себя (если класс одновременно является итератором)

Итератор (Iterator)

Итератор — это объект, который поддерживает два метода: __iter__ и __next__.

Метод __next__

Этот метод обязателен для итератора и должен:

  • Возвращать следующий элемент последовательности
  • Выбросить исключение StopIteration при окончании последовательности
class CustomIterator:
    def __init__(self, max_count):
        self.max_count = max_count
        self.current = 0
    
    def __iter__(self):
        # Итератор обычно возвращает сам себя
        return self
    
    def __next__(self):
        if self.current < self.max_count:
            self.current += 1
            return self.current
        else:
            raise StopIteration

# Использование
iterator = CustomIterator(3)
print(next(iterator))  # 1
print(next(iterator))  # 2
print(next(iterator))  # 3
# print(next(iterator))  # StopIteration

Полный пример: Итерируемый и Итератор вместе

class CountUpTo:
    def __init__(self, max_value):
        self.max_value = max_value
    
    def __iter__(self):
        # Возвращаем новый итератор
        return CountUpToIterator(self.max_value)

class CountUpToIterator:
    def __init__(self, max_value):
        self.max_value = max_value
        self.current = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.current < self.max_value:
            self.current += 1
            return self.current
        else:
            raise StopIteration

# Использование
iterable = CountUpTo(3)
for value in iterable:
    print(value)  # 1, 2, 3

# Каждый раз получаем новый итератор
iterator1 = iter(iterable)
iterator2 = iter(iterable)
print(next(iterator1))  # 1
print(next(iterator1))  # 2
print(next(iterator2))  # 1 (отдельный итератор)

Класс, который является сам и итерируемым, и итератором

class SelfIteratingCounter:
    def __init__(self, max_count):
        self.max_count = max_count
        self.current = 0
    
    def __iter__(self):
        # Возвращаем сам себя
        return self
    
    def __next__(self):
        if self.current < self.max_count:
            self.current += 1
            return self.current
        else:
            raise StopIteration

counter = SelfIteratingCounter(3)
for value in counter:
    print(value)  # 1, 2, 3

Важно: когда класс является одновременно итерируемым и итератором, каждый цикл for использует один и тот же объект состояния. Это может привести к неожиданному поведению.

Генераторы — простой способ создать итератор

Генератор — это функция, которая использует yield для создания итератора:

def count_up_to(max_value):
    current = 0
    while current < max_value:
        current += 1
        yield current

# Генератор автоматически поддерживает __iter__ и __next__
for value in count_up_to(3):
    print(value)  # 1, 2, 3

Генератор содержит:

  • __iter__ — возвращает сам себя
  • __next__ — возобновляет выполнение до следующего yield и возвращает значение
  • Автоматическое выбрасывание StopIteration при окончании функции

Различие между Iterable и Iterator

# Iterable — может быть переиспользован
iterable = [1, 2, 3]
print(list(iterable))  # [1, 2, 3]
print(list(iterable))  # [1, 2, 3] — работает снова

# Iterator — может использоваться только один раз
iterator = iter([1, 2, 3])
print(list(iterator))  # [1, 2, 3]
print(list(iterator))  # [] — истощен

Абстрактные базовые классы (ABC)

Python предоставляет ABC для проверки типов:

from collections.abc import Iterable, Iterator

class MyIterable:
    def __iter__(self):
        return iter([1, 2, 3])

print(isinstance(MyIterable(), Iterable))  # True
print(isinstance([1, 2, 3], Iterable))     # True

# Iterator тоже является Iterable
iterator = iter([1, 2, 3])
print(isinstance(iterator, Iterator))   # True
print(isinstance(iterator, Iterable))   # True (Iterator наследует от Iterable)

Практические примеры

Итератор по диапазону файла

class FileLineIterator:
    def __init__(self, filename):
        self.filename = filename
        self.file = None
    
    def __iter__(self):
        self.file = open(self.filename, 'r')
        return self
    
    def __next__(self):
        line = self.file.readline()
        if line:
            return line.strip()
        else:
            self.file.close()
            raise StopIteration

# Использование
for line in FileLineIterator('file.txt'):
    print(line)

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

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

# Использование с itertools
import itertools

counter = InfiniteCounter()
for value in itertools.islice(counter, 5):
    print(value)  # 0, 1, 2, 3, 4

Резюме требований

Итерируемый объект (Iterable) должен:

  • Реализовать метод __iter__(), возвращающий объект-итератор

Итератор (Iterator) должен:

  • Реализовать метод __iter__(), обычно возвращающий сам себя
  • Реализовать метод __next__(), возвращающий следующий элемент или выбрасывающий StopIteration
  • Поддерживать состояние итерации (текущую позицию)

В своей практике я часто использую генераторы, так как они самый удобный способ создания итераторов, но понимаю и применяю оба подхода в зависимости от требований задачи.

Какие методы должен поддерживать итерируемый объект в Python? | PrepBro