Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как написать итератор?
Итератор — это объект, который позволяет последовательно перебирать элементы коллекции. В Python итератор реализуется через два метода: __iter__() и __next__().
Основной механизм
Для создания итератора нужно:
- Определить метод
__iter__(), который возвращает сам итератор (обычноself) - Определить метод
__next__(), который возвращает следующий элемент - Когда элементы закончились,
__next__()должна вызвать исключениеStopIteration
Простейший итератор
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
# Использование
counter = CountUp(3)
for num in counter:
print(num) # Выведет: 1, 2, 3
Когда вы используете for цикл, Python автоматически:
- Вызывает
__iter__()для получения итератора - Повторно вызывает
__next__()до возникновенияStopIteration - Прерывает цикл при
StopIteration
Итератор с состоянием
class RangeIterator:
def __init__(self, start, end, step=1):
self.current = start
self.end = end
self.step = step
def __iter__(self):
return self
def __next__(self):
if (self.step > 0 and self.current < self.end) or (self.step < 0 and self.current > self.end):
value = self.current
self.current += self.step
return value
else:
raise StopIteration
# Использование
for i in RangeIterator(0, 5):
print(i) # 0, 1, 2, 3, 4
for i in RangeIterator(5, 0, -1):
print(i) # 5, 4, 3, 2, 1
Итератор по строкам файла
class FileLineIterator:
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.rstrip()
else:
self.file.close()
raise StopIteration
# Использование
for line in FileLineIterator(data.txt):
print(line)
Итератор для матрицы
class MatrixIterator:
def __init__(self, matrix):
self.matrix = matrix
self.row = 0
self.col = 0
def __iter__(self):
return self
def __next__(self):
if self.row < len(self.matrix):
value = self.matrix[self.row][self.col]
self.col += 1
if self.col >= len(self.matrix[self.row]):
self.col = 0
self.row += 1
return value
else:
raise StopIteration
# Использование
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
for element in MatrixIterator(matrix):
print(element) # 1, 2, 3, 4, 5, 6, 7, 8, 9
Итератор с фильтрацией
class FilterIterator:
def __init__(self, iterable, predicate):
self.iterable = iter(iterable) # Получаем итератор из объекта
self.predicate = predicate
def __iter__(self):
return self
def __next__(self):
while True:
value = next(self.iterable) # Получаем следующий элемент
if self.predicate(value):
return value
# Использование
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_filter = FilterIterator(data, lambda x: x % 2 == 0)
for num in even_filter:
print(num) # 2, 4, 6, 8, 10
Итератор с трансформацией (map)
class MapIterator:
def __init__(self, iterable, func):
self.iterable = iter(iterable)
self.func = func
def __iter__(self):
return self
def __next__(self):
value = next(self.iterable) # Может вызвать StopIteration
return self.func(value)
# Использование
numbers = [1, 2, 3, 4, 5]
squares = MapIterator(numbers, lambda x: x ** 2)
for square in squares:
print(square) # 1, 4, 9, 16, 25
Бесконечный итератор
class InfiniteIterator:
def __init__(self, start=0, step=1):
self.current = start
self.step = step
def __iter__(self):
return self
def __next__(self):
value = self.current
self.current += self.step
return value
# Использование (осторожно! Бесконечный цикл)
for i in InfiniteIterator():
print(i)
if i > 5:
break # Нужно остановить вручную
Сравнение: Итератор vs Генератор
Генератор — это более простой способ создать итератор:
# Итератор (классический способ)
class CountIterator:
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
# Генератор (более простой способ)
def count_generator(max):
current = 0
while current < max:
current += 1
yield current
# Использование одинаковое
for i in CountIterator(3):
print(i)
for i in count_generator(3):
print(i)
Когда использовать собственный итератор
- Когда состояние сложное: если нужно отслеживать несколько переменных
- Когда нужна инициализация: когда требуется подготовка ресурсов
- Когда нужна очистка: когда требуется закрыть файлы или соединения
- Когда нужна переиспользуемость: когда итератор вызывается много раз
Лучшие практики
class SafeIterator:
def __init__(self, data):
if not hasattr(data, __iter__):
raise TypeError(f"{type(data)} is not iterable")
self.data = data
self.index = 0
def __iter__(self):
# Возвращаем новый итератор для переиспользования
return iter(self.data)
def __next__(self):
if self.index < len(self.data):
value = self.data[self.index]
self.index += 1
return value
else:
raise StopIteration
Ключевые моменты
- Два метода:
__iter__()и__next__() - StopIteration: исключение для завершения итерации
- Состояние: итератор должен помнить текущую позицию
- Интеграция с for: Python автоматически использует протокол итератора
- Генераторы: проще, но итераторы дают больше контроля
Итераторы — фундаментальная часть Python, используемая в циклах, списковых выражениях и многих встроенных функциях (map, filter, zip).