Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Приведи пример итератора
Краткий ответ
Итератор — это объект, который реализует два метода: __iter__() (возвращает сам итератор) и __next__() (возвращает следующий элемент или выбрасывает StopIteration). Итераторы позволяют последовательно обходить элементы без загрузки всех в память одновременно.
Базовый пример: Простой итератор
Встроенные итераторы Python
# Списки, кортежи, строки — все iterable
my_list = [1, 2, 3]
# Получаем итератор из iterable
iterator = iter(my_list)
# Используем next() для получения элементов
print(next(iterator)) # 1
print(next(iterator)) # 2
print(next(iterator)) # 3
# print(next(iterator)) # StopIteration исключение!
Кастомный итератор с нуля
class CountUp:
"""Итератор, который считает от 1 до n"""
def __init__(self, max):
self.max = max
self.current = 0
def __iter__(self):
"""Возвращает сам итератор"""
return self
def __next__(self):
"""Возвращает следующий элемент"""
self.current += 1
if self.current <= self.max:
return self.current
else:
raise StopIteration
# Использование
counter = CountUp(3)
for num in counter:
print(num) # 1, 2, 3
# Эквивалентно:
counter2 = CountUp(3)
iterator = iter(counter2)
while True:
try:
print(next(iterator))
except StopIteration:
break
Практические примеры
Пример 1: Итератор чтения файла
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.rstrip()
else:
self.file.close()
raise StopIteration
# Использование
for line in FileIterator(data.txt):
print(line) # Каждая строка загружается по одной
Пример 2: Итератор бесконечной последовательности
class InfiniteCounter:
"""Итератор, генерирующий бесконечный поток чисел"""
def __init__(self, start=0):
self.current = start
def __iter__(self):
return self
def __next__(self):
self.current += 1
return self.current
# Использование (с ограничением!)
for i, num in enumerate(InfiniteCounter()):
print(num)
if i >= 4: # Остановимся после 5 элементов
break
# Выведет: 1, 2, 3, 4, 5
Пример 3: Итератор для обхода дерева
class TreeNode:
def __init__(self, value, left=None, right=None):
self.value = value
self.left = left
self.right = right
class TreeIterator:
"""In-order обход двоичного дерева"""
def __init__(self, root):
self.stack = []
self.current = root
self._go_to_left()
def _go_to_left(self):
while self.current:
self.stack.append(self.current)
self.current = self.current.left
def __iter__(self):
return self
def __next__(self):
if not self.stack:
raise StopIteration
node = self.stack.pop()
self.current = node.right
self._go_to_left()
return node.value
# Использование
root = TreeNode(2,
TreeNode(1),
TreeNode(3)
)
for value in TreeIterator(root):
print(value) # 1, 2, 3
Пример 4: Итератор для батчей данных
class BatchIterator:
"""Разбивает список на батчи"""
def __init__(self, data, batch_size):
self.data = data
self.batch_size = batch_size
self.current_index = 0
def __iter__(self):
return self
def __next__(self):
if self.current_index >= len(self.data):
raise StopIteration
batch = self.data[self.current_index:self.current_index + self.batch_size]
self.current_index += self.batch_size
return batch
# Использование
data = list(range(10))
for batch in BatchIterator(data, batch_size=3):
print(batch) # [0, 1, 2], [3, 4, 5], [6, 7, 8], [9]
Генератор — упрощённый способ создания итератора
Генератор — это функция, использующая yield. Она автоматически создаёт итератор:
# Версия 1: Кастомный класс итератор
class CountUpClass:
def __init__(self, max):
self.max = max
self.current = 0
def __iter__(self):
return self
def __next__(self):
self.current += 1
if self.current <= self.max:
return self.current
raise StopIteration
# Версия 2: Генератор (проще!)
def count_up(max):
current = 0
while current < max:
current += 1
yield current
# Оба работают одинаково
for num in CountUpClass(3):
print(num) # 1, 2, 3
for num in count_up(3):
print(num) # 1, 2, 3
Встроенные итераторы в Python
Файловый дескриптор
# Файл — это итератор!
with open(data.txt) as f:
for line in f: # Автоматически вызывает __next__()
print(line.rstrip())
dict.keys(), dict.values(), dict.items()
data = {"a": 1, "b": 2}
# Это итераторы
for key in data.keys():
print(key)
for value in data.values():
print(value)
zip(), map(), filter()
list1 = [1, 2, 3]
list2 = ["a", "b", "c"]
# zip возвращает итератор пар
for num, letter in zip(list1, list2):
print(num, letter) # 1 a, 2 b, 3 c
# map возвращает итератор трансформированных значений
for squared in map(lambda x: x ** 2, list1):
print(squared) # 1, 4, 9
# filter возвращает итератор отфильтрованных значений
for even in filter(lambda x: x % 2 == 0, list1):
print(even) # 2
Итератор vs Iterable: Ключевая разница
# Iterable: объект, который ЕЩЁ НЕ итератор
my_list = [1, 2, 3]
print(hasattr(my_list, "__iter__")) # True (iterable)
print(hasattr(my_list, "__next__")) # False (не итератор)
# Iterator: объект, который ВСЕ методы
iterator = iter(my_list)
print(hasattr(iterator, "__iter__")) # True
print(hasattr(iterator, "__next__")) # True (итератор!)
# Итератор всегда вызывается для себя
print(iter(iterator) is iterator) # True
print(iter(my_list) is my_list) # False
Практический паттерн: Ленивая генерация данных
class DatabaseCursor:
"""Итератор для ленивого чтения из БД"""
def __init__(self, query, batch_size=1000):
self.query = query
self.batch_size = batch_size
self.offset = 0
self.exhausted = False
def __iter__(self):
return self
def __next__(self):
if self.exhausted:
raise StopIteration
# Симулируем загрузку батча из БД
results = self._fetch_batch()
if not results:
self.exhausted = True
raise StopIteration
self.offset += len(results)
return results
def _fetch_batch(self):
# Симуляция SQL запроса
return list(range(self.offset, min(self.offset + self.batch_size, 5000)))
# Использование
for batch in DatabaseCursor("SELECT * FROM users"):
print(f"Загружен батч: {len(batch)} записей")
Выводы
- Итератор = объект с методами
__iter__()и__next__() - Iterable = объект с методом
__iter__() - Генератор = функция с
yield(упрощённое создание итератора) - Применение: обход данных без загрузки в память, ленивое вычисление, кастомные последовательности