Генераторы Python: что это такое и зачем они нужны
Генераторы Python: что это такое и зачем они нужны
Генераторы в Python создают последовательности данных. Они не занимают много памяти, а код с ними работает быстрее. Рассказываем, как их создавать и использовать.
Если программист работает с большими объёмами данных, важно не загружать всю информацию в память, а делать это постепенно. Для этого в Python используются генераторы — специальные объекты, которые по требованию генерируют элементы последовательности.
Обычная функция в Python завершает работу после return и возвращает результат. Генератор работает иначе. Вместо return он использует yield, который приостанавливает выполнение, но сохраняет текущее состояние. При следующем вызове выполнение продолжается с того же момента, где оно было остановлено.
Генераторы в Python используются для решения нескольких задач:
● Снижение нагрузки на память. Генераторы помогают обрабатывать большие объёмы данных, например считывать файлы построчно без загрузки в оперативную память.
● Работа с бесконечными последовательностями. Генераторы создают потоки данных, например случайные числа или значения в цикле без предела.
● Оптимизация кода. Они делают код компактнее и удобнее: не нужно использовать дополнительные структуры для хранения промежуточных данных.
Важно отличать генератор от итератора — об этом часто спрашивают разработчиков на собеседованиях. Генератор представляет собой разновидность итератора, но его проще реализовать. Итератор — это объект с методами __iter__() и __next__(), который вручную управляет состоянием. Генератор создаётся с помощью функции с yield, автоматически запоминает, где был остановлен, и продолжает выполнение с этого места при следующем вызове. Итераторы удобны для работы со сложными структурами, а генераторы лучше подходят для потоковой обработки данных и бесконечных последовательностей.
Освоить бэкенд-разработку с нуля всего за 10 месяцев можно на курсе «Python-разработчик». Студенты изучают алгоритмы и структуры данных, API, асинхронность, а навыки отрабатывают на специальном онлайн-тренажёре.
В Python генератор можно создать двумя способами:
1. С помощью функции с yield.
2. С помощью генераторного выражения.
Создание генератора через yield
Генератор — это функция, которая возвращает значения по очереди с помощью yield, а не завершает работу, как при return. Она запоминает, где остановилась, и при следующем вызове продолжает выполнение с того же места. Например, генератор ниже создаёт последовательность чисел:
def simple_generator():
yield 1
yield 2
yield 3
gen = simple_generator()
print(next(gen)) # 1
print(next(gen)) # 2
print(next(gen)) # 3
Попытка вызвать next(gen) ещё раз приведёт к ошибке StopIteration, так как элементы закончились.
Генераторное выражение
Генератор можно создать в одну строку с помощью генераторного выражения. Этот способ аналогичен списковым включениям, но вместо [ ] используют ( ). Вот как может выглядеть код:
gen_exp = (x ** 2 for x in range(5))
print(next(gen_exp)) # 0
print(next(gen_exp)) # 1
print(next(gen_exp)) # 4
Дальше расскажем про генераторные выражения подробнее.
Генераторные выражения — это компактный способ создания генераторов. Выражения позволяют экономить память, так как вычисляют значения по мере необходимости, а не создают сразу весь список.
Генераторное выражение выглядит как списковое включение, но использует круглые скобки ( ) вместо квадратных [ ]:
(expression for item in iterable if condition)
● expression — что делать с каждым элементом;
● item — переменная для текущего элемента;
● iterable — последовательность (например, список, кортеж, диапазон);
● if condition (необязательно) — фильтр для выбора элементов.
Допустим, нужно создать последовательность квадратов чисел от 0 до 9. Значения будут вычисляться по мере необходимости, а не загружаться в память сразу:
gen = (x ** 2 for x in range(10))
print(next(gen)) # 0
print(next(gen)) # 1
print(next(gen)) # 4
Генераторы — это полезный инструмент для работы с последовательностями данных, особенно когда нужно экономить память. Разберём основные способы работы с генераторами.
Генераторы в Python особенно полезны, когда работа идёт с большими объёмами данных, потоками информации или бесконечными последовательностями. Рассмотрим реальные примеры, где генераторы могут быть полезны.
● Чтение больших файлов построчно. Если файл очень большой, загружать его целиком в память неэффективно. Генератор позволяет читать файл построчно:
def read_large_file(filename):
with open(filename, "r", encoding="utf-8") as file:
for line in file:
yield line.strip() # Убираем лишние пробелы
# Использование:
for line in read_large_file("huge_data.txt"):
print(line) # Читаем строки по одной
● Бесконечные последовательности — например, ID пользователей. Генератор позволяет создавать неограниченные последовательности и не хранить их в памяти.
def unique_id_generator():
id = 1
while True:
yield id
id += 1
id_gen = unique_id_generator()
print(next(id_gen)) # 1
print(next(id_gen)) # 2
print(next(id_gen)) # 3
● Генерация случайных данных. Генератор можно использовать для создания случайных паролей:
import random
import string
def random_password(length=8):
while True:
yield ''.join(random.choices(string.ascii_letters + string.digits, k=length))
password_gen = random_password()
print(next(password_gen)) # Генерирует случайный пароль
print(next(password_gen))
● Постепенная загрузка данных из API. При работе с API лучше загружать данные постепенно, а не всю информацию сразу:
import requests
def fetch_data(url):
response = requests.get(url, stream=True)
for line in response.iter_lines():
if line:
yield line.decode('utf-8')
# Использование:
for data in fetch_data("https://example.com/large-data"):
print(data) # Читаем построчно
Совет эксперта
Читать также: