← Назад к вопросам
Как превратить обычный класс в итерируемый в Python?
1.0 Junior🔥 191 комментариев
#Python Core
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как сделать класс итерируемым в Python
Чтобы превратить обычный класс в итерируемый (то есть использовать его в цикле for), нужно реализовать специальные методы: __iter__() и __next__().
Способ 1: Метод __iter__() с __next__()
class CountUp:
"""Класс, который считает от 1 до N"""
def __init__(self, max_value):
self.max_value = max_value
self.current = 0
def __iter__(self):
"""Возвращает объект итератора (самого себя)"""
self.current = 0
return self
def __next__(self):
"""Возвращает следующее значение"""
if self.current < self.max_value:
self.current += 1
return self.current
else:
raise StopIteration # Сигнал конца итерации
# Использование
counter = CountUp(5)
for number in counter:
print(number) # Output: 1, 2, 3, 4, 5
Что здесь происходит:
__iter__()вызывается один раз при входе в цикл for__next__()вызывается на каждой итерации- Когда
__next__()выброситStopIteration, цикл завершится
Способ 2: Методы __iter__() возвращает отдельный итератор
Это более правильный подход, если класс нужно использовать несколько раз:
class CountUpIterator:
"""Отдельный класс-итератор"""
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
raise StopIteration
class CountUp:
"""Итерируемый класс"""
def __init__(self, max_value):
self.max_value = max_value
def __iter__(self):
"""Возвращает новый итератор при каждом вызове"""
return CountUpIterator(self.max_value)
# Использование
counter = CountUp(3)
# Первый проход
for num in counter:
print(num) # Output: 1, 2, 3
# Второй проход (будет работать потому что каждый раз создаётся новый итератор)
for num in counter:
print(num) # Output: 1, 2, 3
Способ 3: Генератор (самый простой способ)
Вместо создания отдельного класса-итератора можно использовать функцию-генератор с yield:
class CountUp:
"""Итерируемый класс с использованием генератора"""
def __init__(self, max_value):
self.max_value = max_value
def __iter__(self):
"""Генератор в методе __iter__"""
for i in range(1, self.max_value + 1):
yield i
# Использование
counter = CountUp(5)
for num in counter:
print(num) # Output: 1, 2, 3, 4, 5
# Можно применять несколько раз
for num in counter:
print(num) # Output: 1, 2, 3, 4, 5
Это наиболее чистый и читаемый способ.
Практический пример: итерирование по файлам в директории
import os
from pathlib import Path
class DirectoryIterator:
"""Класс для итерирования по файлам директории"""
def __init__(self, directory_path):
self.directory = Path(directory_path)
def __iter__(self):
"""Генератор для обхода файлов"""
for file in sorted(self.directory.glob("*.txt")):
yield file.name
# Использование
files = DirectoryIterator(".")
for filename in files:
print(f"Found: {filename}")
Добавление поддержки срезов с __getitem__
Можно сделать класс итерируемым даже без __iter__(), если реализовать __getitem__() с целочисленным индексом:
class SimpleList:
"""Класс с поддержкой индексирования"""
def __init__(self, items):
self.items = items
def __getitem__(self, index):
return self.items[index]
def __len__(self):
return len(self.items)
# Использование
my_list = SimpleList([10, 20, 30, 40])
for item in my_list: # Python автоматически использует __getitem__
print(item) # Output: 10, 20, 30, 40
print(my_list[0]) # Output: 10
print(len(my_list)) # Output: 4
Рекомендации
- Простые случаи → используй генератор (
yield) - Сложная логика итерирования → реализуй
__iter__()и__next__() - Нужна поддержка срезов → добавь
__getitem__()и__len__() - Для читаемости → предпочитай отдельный класс-итератор вместо самоссылающегося
__iter__()