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

Приведи пример итератора

1.2 Junior🔥 251 комментариев
#Python Core

Комментарии (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 (упрощённое создание итератора)
  • Применение: обход данных без загрузки в память, ленивое вычисление, кастомные последовательности