7 May 2024

Осваиваем генераторы в Python: улучшение производительности с помощью yield

7 May 2024

Осваиваем генераторы в Python: улучшение производительности с помощью yield

Как видим, в первом случае код генерирует диапазон чисел, а во втором — создает объект generator object, который является итератором. Таким образом мы можем отложить вычисление элементов последовательности до тех пор, пока в них не возникнет необходимость, чем опять же снижаем нагрузку на ресурсы. Итератор, в свою очередь, это объект, по которому можно итерироваться. Создадим простую генераторную функцию которая возвращает число и уменьшает его на единицу. Создать генератор можно не только используя генераторную функцию, но и с помощью генераторного выражения, которое еще называют Системное тестирование generator comprehension.

В языке программирования Python итерируемые объекты представлены классом collections.abc.Iterator:

Генераторы в языке Python

В отличие от оператора return, который завершает выполнение функции и возвращает генератор списков python результат, yield позволяет возвращать результат без завершения работы. Это делает функции идеальными для ленивых вычислений, где нужно обрабатывать информацию шаг за шагом, а не всё сразу. "Под капотом" цикл for вызывает у генератора метод __iter__, который возвращает итератор и на каждой итерации цикла вызывается метод __next__ у полученного итератора. Один из наиболее распространенных случаев использования функций – это обработка больших файлов. Представьте, что вам нужно читать большой текстовый файл построчно и обрабатывать его информацию. Вместо того чтобы загружать весь файл в память, вы можете использовать генератор для построчного чтения и обработки файла.

Генераторы в языке Python

Получение значений из генератора

Получить значение из генератора можно в цикле или используя функции https://deveducation.com/ next и send. Здесь представлена фикстура в виде генератора которая создает сессию для работы с базой данных до выполнения каждого теста. В строке yield from get_db_session(session_local) управление передается в вызывающий код и выполняется тест. После выполнения теста управление снова возвращается в генератор и выполняется оставшаяся часть после yeld - очистка таблиц в базе данных.Ну и наконец, генераторы используются в асинхронном коде.

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

  • Это особенно важно при обработке больших файлов или наборов данных.
  • Генераторы используются и при написании тестов с использованием библиотеки pytest.
  • При вызове next, send или throw функция main делегирует работу сначала генератору gen и только после того как генератор gen завершит свою работу и отдаст все значения, начинает выполняться генератор gen_2.
  • В примере ниже происходит открытие файла до входа в блок with и закрытие файла при выходе из блока with.
  • Это позволяет работать с файлами, которые могут быть слишком большими для стандартных методов обработки, не перегружая память.

Вызов next и send(None) эквивалентны и приводят к одному и тому же результату. Обратите внимание на скобки при создании генераторного выражения. Если бы мы использовали квадратные, то это было бы уже не генераторное выражение, а list comprehension и переменная gen была бы уже не генератором, а обычным списком. При этом стоит учитывать, что генераторные выражения — это в первую очередь выражения, со всеми вытекающими ограничениями.

Генераторы в языке Python

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

Использование генераторов предоставляет несколько ключевых преимуществ. Так как значения генерируются по одному, не нужно хранить все элементы коллекции в оперативной памяти. Это особенно важно при обработке больших файлов или наборов данных. При этом он сам реализует метод __iter__ из-за чего сам является итерируемым объектом.

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

Рассмотрим использование генератора для создания контекстного менеджера. Как правило контекстный менеджер применяется в блоке with и используется когда нужно выполнить какую-то работу до входа в блок with и при выходе из него. В примере ниже происходит открытие файла до входа в блок with и закрытие файла при выходе из блока with. Встретив return генератор выбрасывает исключение StopIteration, а возвращенное значение записывается в объект StopIteration в атрибут value. Теперь при четвертом вызове next отловим исключение StopIteration и выведем значение, которое хранится в атрибуте value этого исключения. Как видите в этом случае возвращаются объекты генераторов, но не сами значения из этих генераторов.

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

Используя синтаксис async def мы определяем корутину, а любая корутина является генератором. Для примера рассмотрим устаревший синтаксис создания корутин. Здесь мы явно создаем генератор и оборачиваем декоратором coroutine из библиотеки asyncio.

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

Видим что gen_function имеет тип function и к тому же это еще и генераторная функция. При вызове gen_function() вернулся объект gen который является генератором. Асинхронные генераторы идеально подходят для работы с сетевыми запросами, так как они позволяют обрабатывать ответ от сервера по мере его поступления.

© 2022 All Rights Reserved
Design and Develop by MR GREAT