← Назад к вопросам
Что общего у генератора и итератора в 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
На практике генератор проще писать для большинства случаев, но итератор лучше, когда нужна сложная логика и состояние.