Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI21 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Итератор vs Генератор
Это часто путают, но это разные концепции. Генератор — это частный случай итератора, созданный функцией.
Определения
Итератор:
- Объект класса, который реализует методы iter() и next()
- Может содержать состояние и логику в методах
- Создаётся явно через class
- Более гибкий и контролируемый
Генератор:
- Функция, содержащая ключевое слово yield
- Возвращает объект генератора (который является итератором)
- Более компактный и читаемый
- Автоматически реализует iter() и next()
Практическое сравнение
# 1. ИТЕРАТОР (через класс)
class CountUpIterator:
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
iter_obj = CountUpIterator(3)
for num in iter_obj:
print(num) # 1, 2, 3
# 2. ГЕНЕРАТОР (функция с yield)
def count_up_generator(max):
current = 0
while current < max:
current += 1
yield current
gen_obj = count_up_generator(3)
for num in gen_obj:
print(num) # 1, 2, 3
# Оба дают одинаковый результат, но генератор просще!
Ключевые различия
| Аспект | Итератор | Генератор |
|---|---|---|
| Определение | Класс с iter/next | Функция с yield |
| Код | Многострочный, explicit | Компактный, implicit |
| Состояние | Хранится в self.* | Хранится автоматически |
| Контроль | Полный контроль | Меньше контроля |
| Память | Хранит всё состояние | Лениво вычисляет |
| Легко читать | Меньше | Больше |
Генератор — это итератор!
def my_generator():
yield 1
yield 2
yield 3
gen = my_generator()
# Генератор имеет методы __iter__ и __next__
print(hasattr(gen, '__iter__')) # True
print(hasattr(gen, '__next__')) # True
# Можно вызвать явно
print(next(gen)) # 1
print(next(gen)) # 2
print(next(gen)) # 3
try:
next(gen)
except StopIteration:
print("Генератор исчерпан")
Когда использовать
Используй генератор когда:
- Нужна простая последовательность значений
- Логика простая (< 20 строк)
- Нужна ленивое вычисление (экономия памяти)
- Читаемость важна
# Чтение большого файла построчно
def read_large_file(file_path):
with open(file_path) as f:
for line in f:
yield line.strip()
for line in read_large_file('huge.txt'):
process(line) # обрабатываем построчно, не загружая в память
Используй итератор когда:
- Нужна сложная логика
- Нужны доп. методы и свойства
- Состояние сложное (несколько переменных)
- Нужна гибкость
# Сложный итератор с дополнительным функционалом
class WindowIterator:
def __init__(self, data, window_size):
self.data = data
self.window_size = window_size
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index + self.window_size > len(self.data):
raise StopIteration
window = self.data[self.index:self.index + self.window_size]
self.index += 1
return window
def reset(self):
self.index = 0
w = WindowIterator([1, 2, 3, 4, 5], 3)
for window in w:
print(window) # [1,2,3], [2,3,4], [3,4,5]
Бесконечные генераторы
# Генератор может быть бесконечным
def infinite_numbers():
n = 0
while True:
yield n
n += 1
gen = infinite_numbers()
print(next(gen)) # 0
print(next(gen)) # 1
print(next(gen)) # 2
# Может работать бесконечно
# Практическое применение
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
fib = fibonacci()
for _ in range(5):
print(next(fib)) # 0, 1, 1, 2, 3
Generator Expression (выражение-генератор)
# Похоже на list comprehension, но экономит память
squares_list = [x**2 for x in range(1000000)] # память: ~40MB
squares_gen = (x**2 for x in range(1000000)) # память: ~几KB
print(next(squares_gen)) # 0
print(next(squares_gen)) # 1
print(next(squares_gen)) # 4
Важные моменты
- Генератор можно использовать только один раз
- После StopIteration объект "мёртв" — нужно создать новый
- Генератор более читаем, итератор более гибкий
- Оба следуют протоколу итератора
- Большинство встроенных функций ожидают итераторы
Вывод: генератор — это просто удобный способ создать итератор функцией вместо класса.