Найти в Дзене
Креативный дизайн

Генераторы в Python: Искусство лени и эффективности

Генераторы в Python представляют собой мощный инструмент для управления большими наборами данных и сложными функциональными вычислениями. Прелесть этих конструкций заключается в их способности выдавать значения по требованию, минимизируя расход памяти и делая программный код более ясным и компактным. В этой статье я расскажу вам, как работают генераторы, как они реализуются, и продемонстрирую их использование на примерах. Начнем с главного концептуального элемента генераторов — оператора yield. Этот оператор предоставляет возможности, аналогичные оператору return, с одной ключевой разницей: yield «замораживает» состояние функции. Это означает, что при следующем вызове функции выполнение продолжится с того места, где оно было приостановлено. Благодаря этому эффекту, yield позволяет создавать итераторы, которые работают лениво, выдавая значения по мере необходимости. Тот же код ниже для копирования и вставки в программу. Не забывайте про необходимый отступ пробелами в определённых местах
Оглавление

Генераторы в Python представляют собой мощный инструмент для управления большими наборами данных и сложными функциональными вычислениями. Прелесть этих конструкций заключается в их способности выдавать значения по требованию, минимизируя расход памяти и делая программный код более ясным и компактным. В этой статье я расскажу вам, как работают генераторы, как они реализуются, и продемонстрирую их использование на примерах.

Понимание Оператора yield

Начнем с главного концептуального элемента генераторов — оператора yield. Этот оператор предоставляет возможности, аналогичные оператору return, с одной ключевой разницей: yield «замораживает» состояние функции. Это означает, что при следующем вызове функции выполнение продолжится с того места, где оно было приостановлено. Благодаря этому эффекту, yield позволяет создавать итераторы, которые работают лениво, выдавая значения по мере необходимости.

Рассмотрим пример с генерацией чисел Фибоначчи:

Выше написано правильное написание кода
Выше написано правильное написание кода
Тот же код ниже для копирования и вставки в программу. Не забывайте про необходимый отступ пробелами в определённых местах в начале строки, так как код на сервере блога может отображаться некорректно.

def fibonacci(number):
a, b = 0, 1 # Начальные значения для последовательности Фибоначчи
for _ in range(number):
yield a # Возвращаем текущее значение
a, b = b, a + b # Обновляем значения a и b для следующего числа

# Используем функцию для генерации последовательности Фибоначчи из первых 20 чисел
fib_seq = fibonacci(number=20)
for i_value in fib_seq:
print(i_value)

Разбор кода

  1. def fibonacci(number): — определяем функцию, которая принимает один аргумент, указывающий, сколько чисел Фибоначчи мы хотим сгенерировать.
  2. a, b = 0, 1 — инициализация начальных значений для последовательности Фибоначчи.
  3. for _ in range(number): — цикл, который запускается заданное количество раз.
  4. yield a — отдаем текущее значение a и «замораживаем» функцию.
  5. a, b = b, a + b — обновляем значения для следующей итерации.

В результате каждой итерации мы получаем следующее число в последовательности до тех пор, пока не пройдем по всем значениям.

Результаты работы кода:

-3
Оператор yield — переводится как произвести или выдать значение. Этот оператор очень похож на return, но разница заключается в следующем — он «замораживает» функцию (сохраняет своё состояние), а не завершает полностью её работу.
Оператор yield возвращает значение, при этом «замораживает» состояние функции вместе со значением в ней.
Пройтись циклом по генератору можно только один раз.

В результате мы реализовали ленивое вычисление нашей последовательности, превратив обычную нашу функцию в генератор.

Чем Генераторы отличаются от Итераторов

  • Генераторы являются формой итераторов, но с важной особенностью: они реализованы в виде функций. Это ускоряет процесс разработки, поскольку Python берет на себя автоматизацию таких методов, как __iter__ и __next__.
  • Генераторы позволяют обрабатывать последовательности, которые могут не помещаться целиком в памяти, выдавая элементы только по мере необходимости.
  • Генераторы используются для ленивых вычислений.
  • Генераторы можно сказать «родственники» итераторов, так как генераторы — это итераторы, реализованные в виде функции и по которым можно итерироваться только один раз.
  • Генераторы хорошо использовать при разных тяжеловесных операциях, где нужно вычислять значения по требованию.
  • Еще одно определение генераторов: генераторы — это функции, которые используют выражение yield.
  • Генераторы не могут возвращать сразу все значения. Вместо этого они выдают значения по готовности.
  • Python автоматизирует запоминание контекста генератора: текущий поток управления, значения локальных переменных и так далее.
  • Как и у итераторов каждый вызов методов __next__ у объекта генератора возвращает значения. Метод __iter__ так же реализуется в автоматическом режиме.
  • Генераторы можно использовать везде, где требуются итераторы.
  • С помощью генераторов можно сделать код более компактным и читабельным.

Итераторы, напротив, применяются для структур данных, которым требуется удерживать все их элементы в памяти, такие как списки или словари.

Еще одной отличительной особенностью итераторов от генераторов заключается в области применения. Итераторы используются в основном для итерируемых объектов, которые уже загружены в память, такие как списки, словари, кортежи и прочее. То есть значения уже вычислены и мы по ним просто проходимся в цикле for.

  • Используется итератор для структур данных.
  • Итераторы используются для реализации кода в сложной структуре.
  • В Python мы можем любой объект сделать итерируемым просто добавив ещё два метода в уже готовый класс.

Генератор же используется для генерации данных «на лету». И часто используется для генерации «ленивых вычислений», вместо того что бы писать большой класс.

return завершает генерацию и воспринимается как завершение генерации и аналогичен команде raise StopIteration.

Пример завершения Генерации с использованием return

Посмотрим на пример генератора, который завершает свою работу, когда достигает определенного условия:

Выше написано правильное написание кода
Выше написано правильное написание кода
Тот же код ниже для копирования и вставки в программу. Не забывайте про необходимый отступ пробелами в определённых местах в начале строки, так как код на сервере блога может отображаться некорректно.

def fibonacci(number):
cur_val = 0
next_val = 1
for _ in range(number):
yield cur_val
cur_val, next_val = next_val, cur_val + next_val
if cur_val > 10 ** 6:
return
fib_seq = fibonacci(number=1000000000)
for i_value in fib_seq:
print(i_value, end=' ')

Разбор кода

  1. Объект генератора fib_seq создается с поддержкой большого числа возможных значений.
  2. Генерация прерывается return, когда текущее значение превышает миллион, что предотвращает избыточное выполнение.

Результат работы кода:

-5

Генераторные Выражения

В Python вы можете использовать неявные генераторы с помощью генераторных выражений. Они обеспечивают синтаксический сахар для создания простых генераторов и имеют сходство с пониманиями списков, но вместо них они возвращают генераторы.

Например, создание последовательности квадратов чисел:

Выше написано правильное написание кода
Выше написано правильное написание кода
Тот же код ниже для копирования и вставки в программу. Не забывайте про необходимый отступ пробелами в определённых местах в начале строки, так как код на сервере блога может отображаться некорректно.

squares = (x**2 for x in range(10))
for square in squares:
print(square)

Этот подход позволяет легко и просто использовать генераторы для генерации данных на лету без явной их функции.

Генераторы можно не создавать, а использовать генераторные выражения при использовании несложных алгоритмов генерации значений.

В практике создания кода можно не создавать свой собственный генератор, а лишь использовать генераторные выражения. Это синтаксический сахар и более простой способ создавать выражения.

Результат работы кода:

-7

Заключение

Генераторы упрощают задачу обработки большого объема данных и выполнения потенциально длительных операций, требующих ленивых вычислений. Они позволяют писать более компактный и эффективный код, в то время как их использование облегчает понимание и сопровождение. Генераторные выражения и полная реализация функций — это инструменты в Python, которые открывают множество возможностей для оптимизации и улучшения производительности программного обеспечения.

Попробуйте применять генераторы всякий раз, когда перед вами встают задачи обработки тяжелых или объемных наборов данных, и наслаждайтесь улучшениями кода.

Полезные ресурсы:

---------------------------------------------------

Сообщество дизайнеров в VK

https://vk.com/grafantonkozlov

Телеграмм канал сообщества

https://t.me/grafantonkozlov

Архив эксклюзивного контента

https://boosty.to/antonkzv

Канал на Дзен

https://dzen.ru/grafantonkozlov

---------------------------------------------------

Бесплатный Хостинг и доменное имя

https://tilda.cc/?r=4159746

Мощная и надежная нейронная сеть Gerwin AI

https://t.me/GerwinPromoBot?start=referrer_3CKSERJX

GPTs — плагины и ассистенты для ChatGPT на русском языке

https://gptunnel.ru/?ref=Anton

---------------------------------------------------

Донат для автора блога

dzen.ru/grafantonkozlov?donate=true