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

Что общего у генератора и итератора в Python?

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

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

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

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

Что общего у генератора и итератора в Python

Генератор и итератор в Python связаны между собой. Генератор — это частный случай итератора, но это не одно и то же. Давайте разберёмся в различиях и сходствах.

Что такое итератор

Итератор — это объект, который позволяет перемещаться по элементам коллекции один за другим. Он реализует два метода:

  • __iter__() — возвращает сам итератор
  • __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

# Или явно
iterator = iter(counter)
print(next(iterator))  # 1
print(next(iterator))  # 2
print(next(iterator))  # 3
# print(next(iterator))  # StopIteration

Что такое генератор

Генератор — это функция, которая использует ключевое слово yield для возврата значений один за другим. Это компактный способ создания итератора.

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

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

# Или явно
gen = count_up(3)
print(next(gen))  # 1
print(next(gen))  # 2
print(next(gen))  # 3
# print(next(gen))  # StopIteration

Что общего у генератора и итератора

1. Оба реализуют протокол итератора

# Итератор
class MyIterator:
    def __iter__(self):
        return self
    
    def __next__(self):
        # ...
        pass

# Генератор имплицитно реализует протокол
def my_generator():
    yield 1
    yield 2

# Обе поддерживают for loop
for item in MyIterator():
    print(item)

for item in my_generator():
    print(item)

2. Оба используют next() для получения следующего элемента

# Итератор
iterator = MyIterator()
print(next(iterator))

# Генератор
generator = my_generator()
print(next(generator))

# Оба вызывают StopIteration при конце

3. Оба ленивые — вычисляют значения по требованию

def lazy_generator():
    print("Генерирую первое значение")
    yield 1
    print("Генерирую второе значение")
    yield 2

gen = lazy_generator()  # Ничего не печатается!
print(next(gen))  # "Генерирую первое значение" -> 1
print(next(gen))  # "Генерирую второе значение" -> 2

Это ключевое сходство — оба экономят память, вычисляя значения по мере надобности.

4. Оба могут быть использованы с встроенными функциями

# Итератор
sum(MyIterator())
list(MyIterator())
any(MyIterator())

# Генератор
sum(my_generator())
list(my_generator())
any(my_generator())

5. Оба поддерживают send() для двусторонней коммуникации

# Генератор с send()
def echo_generator():
    while True:
        value = yield
        if value:
            print(f"Получено: {value}")

gen = echo_generator()
next(gen)  # Инициализируем
gen.send("Hello")  # Отправляем значение

# Итератор может иметь похожий функционал (но это редко)

Ключевые различия

Синтаксис

# Итератор — класс с методами
class Iterator:
    def __iter__(self):
        return self
    def __next__(self):
        raise StopIteration

# Генератор — функция с yield
def generator():
    yield value

Состояние

# Итератор явно управляет состоянием
class Counter:
    def __init__(self):
        self.current = 0
    
    def __next__(self):
        self.current += 1
        if self.current > 3:
            raise StopIteration
        return self.current

# Генератор управляет состоянием автоматически
def counter():
    current = 0
    while current < 3:
        current += 1
        yield current

Использование памяти

# Итератор может хранить много данных
class BigDataIterator:
    def __init__(self):
        self.data = [i for i in range(1000000)]
        self.index = 0
    
    def __next__(self):
        if self.index >= len(self.data):
            raise StopIteration
        value = self.data[self.index]
        self.index += 1
        return value

# Генератор экономит память
def big_data_generator():
    for i in range(1000000):
        yield i

Тип генератора

def my_gen():
    yield 1

gen = my_gen()
print(type(gen))  # <class 'generator'>
print(isinstance(gen, Iterator))  # True (если импортирован из collections.abc)

# Генератор ЭТО итератор
from collections.abc import Iterator
print(isinstance(gen, Iterator))  # True

Практические примеры использования

Генератор для обработки больших файлов

def read_large_file(file_path):
    with open(file_path) as file:
        for line in file:
            yield line.strip()

# Использование
for line in read_large_file('huge_file.txt'):
    process(line)  # Обрабатываем построчно, не загружая весь файл в память

Итератор для сложной логики

class FibonacciIterator:
    def __init__(self, limit):
        self.limit = limit
        self.a, self.b = 0, 1
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.a > self.limit:
            raise StopIteration
        value = self.a
        self.a, self.b = self.b, self.a + self.b
        return value

for fib in FibonacciIterator(100):
    print(fib)

Генератор для последовательностей

def infinite_sequence():
    number = 0
    while True:
        yield number
        number += 1

# Использование (осторожно с бесконечностью!)
gen = infinite_sequence()
for _ in range(5):
    print(next(gen))  # 0, 1, 2, 3, 4

Когда использовать что

# Генератор — когда нужно просто
def simple_sequence():
    for i in range(1000000):
        yield i

# Итератор — когда нужна сложная логика и состояние
class ComplexSequence:
    def __init__(self, config):
        self.config = config
        self.state = ComplexState()
    
    def __next__(self):
        # Сложная логика с состоянием
        pass

Вывод

Что общего:

  • Оба реализуют протокол итератора (iter и next)
  • Оба ленивые — вычисляют значения по требованию
  • Оба работают с for loops и функциями вроде next()
  • Оба экономят память для больших данных
  • Оба вызывают StopIteration при конце

Главное различие:

  • Генератор — это функция с yield (синтаксический сахар)
  • Итератор — это класс с методами iter и next

На практике генератор проще писать для большинства случаев, но итератор лучше, когда нужна сложная логика и состояние.

Что общего у генератора и итератора в Python? | PrepBro