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

Зачем нужен генератор в Python?

1.3 Junior🔥 171 комментариев
#Python Core

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

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

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

Генераторы в Python

Генератор — это функция, которая возвращает итератор, выдавая значения по одному с помощью yield вместо return. Это мощный инструмент для создания ленивых (lazy) вычислений.

Основная идея

Основное преимущество генераторов — экономия памяти. Вместо создания всего списка в памяти, генератор создаёт значения на лету:

# Способ 1: Обычная функция со списком (неэффективно)
def get_numbers_list(n):
    result = []
    for i in range(n):
        result.append(i * 2)
    return result  # Весь список в памяти сразу

# Использование
for num in get_numbers_list(1_000_000):
    print(num)

# Способ 2: Генератор (экономия памяти)
def get_numbers_generator(n):
    for i in range(n):
        yield i * 2  # Выдаёт по одному значению

# Использование
for num in get_numbers_generator(1_000_000):
    print(num)  # Каждое значение создаётся на месте

С генератором функция не создаёт список из 1 млн элементов в памяти — она выдаёт по одному значению при каждой итерации.

Создание генератора

1. С помощью функции и yield:

def countdown(n):
    while n > 0:
        yield n
        n -= 1

for num in countdown(5):
    print(num)  # 5, 4, 3, 2, 1

2. Expression генератор (generator expression):

# Похоже на list comprehension, но с () вместо []
numbers = [1, 2, 3, 4, 5]
squared_gen = (x ** 2 for x in numbers)  # Генератор
squared_list = [x ** 2 for x in numbers]  # Список

print(type(squared_gen))  # <class generator>
print(type(squared_list))  # <class list>

# Значения создаются при итерации
for val in squared_gen:
    print(val)  # 1, 4, 9, 16, 25

Практические применения

1. Чтение большого файла построчно:

def read_large_file(file_path, chunk_size=1024):
    with open(file_path, rb) as f:
        while True:
            chunk = f.read(chunk_size)
            if not chunk:
                break
            yield chunk  # Выдаём по одному чанку, не загружая весь файл

# Использование
for chunk in read_large_file(huge_file.bin):
    process(chunk)  # Обрабатываем по кусочкам

2. Бесконечные последовательности:

def infinite_counter(start=0):
    n = start
    while True:
        yield n
        n += 1

# Использование
for i, value in enumerate(infinite_counter()):
    print(value)
    if i > 4:
        break  # 0, 1, 2, 3, 4

3. Фибоначчи:

def fibonacci(limit=None):
    a, b = 0, 1
    count = 0
    while limit is None or count < limit:
        yield a
        a, b = b, a + b
        count += 1

for fib in fibonacci(10):
    print(fib)  # 0, 1, 1, 2, 3, 5, 8, 13, 21, 34

4. Обработка цепочки трансформаций:

def numbers_gen():
    for i in range(10):
        yield i

def double(gen):
    for value in gen:
        yield value * 2

def filter_even(gen):
    for value in gen:
        if value % 2 == 0:
            yield value

# Цепочка — данные обрабатываются по ленивому принципу
for val in filter_even(double(numbers_gen())):
    print(val)  # 0, 4, 8, 12, 16

Встроенные функции с генераторами

# map() и filter() возвращают итераторы (похоже на генераторы)
nums = [1, 2, 3, 4, 5]
result = map(lambda x: x ** 2, nums)  # map object, не список
print(list(result))  # [1, 4, 9, 16, 25]

# zip() — тоже генерирует значения на лету
list1 = [1, 2, 3]
list2 = [a, b, c]
for num, letter in zip(list1, list2):
    print(num, letter)  # Значения создаются на месте

Методы генератора

def gen():
    value = yield 1
    print(f"Получено: {value}")
    yield 2

g = gen()
result1 = next(g)  # Выдаст 1, остановится на yield
result2 = g.send("hello")  # Отправит значение в генератор
# Получено: hello
# result2 = 2

Сравнение: Список vs Генератор

import sys

list_comp = [x ** 2 for x in range(1000)]  # ~8000 байт
gen_comp = (x ** 2 for x in range(1000))   # ~100 байт

print(sys.getsizeof(list_comp))  # 8856
print(sys.getsizeof(gen_comp))   # 128

Выводы

  • Генераторы экономят память — вычисления на лету
  • Ленивые вычисления — значения создаются только когда нужны
  • Бесконечные последовательности — можно работать без верхнего предела
  • Производительность — быстрее всего для больших наборов данных
  • Цепочки обработки — элегантная обработка потока данных
Зачем нужен генератор в Python? | PrepBro