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

За что отвечает метод __iter__

2.0 Middle🔥 201 комментариев
#Python Core

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

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

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

За что отвечает метод iter

Метод __iter__ — это магический метод в Python, который делает объект итерируемым. Он отвечает за инициализацию процесса перебора элементов объекта и должен возвращать итератор.

Основная концепция

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

# Базовая иерархия:
# Iterable (имеет __iter__) -> Iterator (имеет __iter__ и __next__)

my_list = [1, 2, 3]

# Когда вы пишете:
for element in my_list:
    print(element)

# Python делает:
iterator = iter(my_list)  # Вызывает my_list.__iter__()
while True:
    try:
        element = next(iterator)  # Вызывает iterator.__next__()
        print(element)
    except StopIteration:
        break

Разница между итерируемым и итератором

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

  • Имеет метод __iter__()
  • Возвращает итератор
  • Примеры: list, tuple, dict, set, string

Итератор (Iterator):

  • Имеет методы __iter__() и __next__()
  • __iter__() возвращает себя (self)
  • __next__() возвращает следующий элемент
  • Поднимает StopIteration когда элементы закончились
# Итерируемый объект НЕ итератор
my_list = [1, 2, 3]
print(hasattr(my_list, "__iter__"))  # True
print(hasattr(my_list, "__next__"))  # False

# Итератор - итерируемый объект
iterator = iter(my_list)
print(hasattr(iterator, "__iter__"))  # True
print(hasattr(iterator, "__next__"))  # True

Создание простого итерируемого класса

class Counter:
    def __init__(self, max):
        self.max = max
    
    def __iter__(self):
        # Возвращает итератор (может быть self или другой объект)
        return CounterIterator(self.max)

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

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

Альтернатива: итератор и итерируемый в одном классе

class SimpleIterator:
    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 SimpleIterator(3):
    print(num)  # 1, 2, 3

Практический пример: итерируемый класс для работы с файлом

class FileReader:
    def __init__(self, filename):
        self.filename = filename
    
    def __iter__(self):
        return FileIterator(self.filename)

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

# Использование
for line in FileReader("data.txt"):
    print(line)  # Печатает строку за строкой

Встроенные типы с iter

# Список
my_list = [1, 2, 3]
iterator = iter(my_list)  # Вызывает __iter__
print(next(iterator))  # 1
print(next(iterator))  # 2
print(next(iterator))  # 3
# next(iterator)  # StopIteration

# Словарь (по ключам по умолчанию)
my_dict = {"a": 1, "b": 2, "c": 3}
for key in my_dict:  # Использует __iter__
    print(key)  # a, b, c

# Строка
for char in "hello":  # Использует __iter__
    print(char)  # h, e, l, l, o

Использование с встроенными функциями

class CustomRange:
    def __init__(self, start, end):
        self.start = start
        self.end = end
    
    def __iter__(self):
        self.current = self.start
        return self
    
    def __next__(self):
        if self.current < self.end:
            self.current += 1
            return self.current - 1
        else:
            raise StopIteration

# Работает с встроенными функциями благодаря __iter__
custom = CustomRange(0, 5)

print(list(custom))  # [0, 1, 2, 3, 4]
print(max(CustomRange(10, 20)))  # 19
print(sum(CustomRange(1, 5)))  # 6

# Распаковка благодаря __iter__
a, b, c = CustomRange(0, 3)  # a=0, b=1, c=2

Контекстный менеджер с итератором

class DataIterator:
    def __init__(self, data):
        self.data = data
        self.index = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.index < len(self.data):
            result = self.data[self.index]
            self.index += 1
            return result
        else:
            raise StopIteration
    
    def __len__(self):
        return len(self.data)

data_iter = DataIterator([10, 20, 30, 40])
for value in data_iter:
    print(value)  # 10, 20, 30, 40

# Можно переитерировать, создав новый объект
for value in DataIterator([10, 20, 30, 40]):
    print(value)

Генераторы используют iter автоматически

def my_generator(max):
    current = 0
    while current < max:
        yield current
        current += 1

# Генератор имеет __iter__ и __next__ по умолчанию
gen = my_generator(3)

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

# Работает в цикле
for num in gen:
    print(num)  # 0, 1, 2

Важные замечания

  1. iter должен вернуть итератор — объект с методом __next__
  2. Можно возвращать self — если класс одновременно является итератором
  3. Множественная итерация — список позволяет множественную итерацию, но некоторые итераторы нет
my_list = [1, 2, 3]

# Можно итерировать многократно
for x in my_list:
    print(x)

for x in my_list:  # Работает снова
    print(x)

# Но с итератором файла это не сработает
reader = FileReader("data.txt")
for line in reader:
    print(line)

for line in reader:  # Ничего не напечатает - файл закрыт
    print(line)

Резюме

Метод __iter__ критически важен для:

  • Использования объекта в цикле for
  • Распаковки значений
  • Работы с встроенными функциями (list, sum, max, etc.)
  • Создания пользовательских типов данных с поддержкой итерации

В заключение: __iter__ — это способ Python говорить объекту: "Дай мне итератор, я буду доставать из него элементы один за другим".

За что отвечает метод __iter__ | PrepBro