Как видим, в первом случае код генерирует диапазон чисел, а во втором — создает объект generator object, который является итератором. Таким образом мы можем отложить вычисление элементов последовательности до тех пор, пока в них не возникнет необходимость, чем опять же снижаем нагрузку на ресурсы. Итератор, в свою очередь, это объект, по которому можно итерироваться. Создадим простую генераторную функцию которая возвращает число и уменьшает его на единицу. Создать генератор можно не только используя генераторную функцию, но и с помощью генераторного выражения, которое еще называют Системное тестирование generator comprehension.
В отличие от оператора return, который завершает выполнение функции и возвращает генератор списков python результат, yield позволяет возвращать результат без завершения работы. Это делает функции идеальными для ленивых вычислений, где нужно обрабатывать информацию шаг за шагом, а не всё сразу. "Под капотом" цикл for вызывает у генератора метод __iter__, который возвращает итератор и на каждой итерации цикла вызывается метод __next__ у полученного итератора. Один из наиболее распространенных случаев использования функций – это обработка больших файлов. Представьте, что вам нужно читать большой текстовый файл построчно и обрабатывать его информацию. Вместо того чтобы загружать весь файл в память, вы можете использовать генератор для построчного чтения и обработки файла.
Получить значение из генератора можно в цикле или используя функции https://deveducation.com/ next и send. Здесь представлена фикстура в виде генератора которая создает сессию для работы с базой данных до выполнения каждого теста. В строке yield from get_db_session(session_local) управление передается в вызывающий код и выполняется тест. После выполнения теста управление снова возвращается в генератор и выполняется оставшаяся часть после yeld - очистка таблиц в базе данных.Ну и наконец, генераторы используются в асинхронном коде.
Вызов next и send(None) эквивалентны и приводят к одному и тому же результату. Обратите внимание на скобки при создании генераторного выражения. Если бы мы использовали квадратные, то это было бы уже не генераторное выражение, а list comprehension и переменная gen была бы уже не генератором, а обычным списком. При этом стоит учитывать, что генераторные выражения — это в первую очередь выражения, со всеми вытекающими ограничениями.
Это предотвращает блокировку программы, давая возможность выполнять другие операции, пока ожидается ответ от удаленного сервера. Еще одно полезное применение функций – это работа с бесконечными последовательностями. Генераторы идеально подходят для создания таких последовательностей, как генераторы случайных чисел или вычисления чисел Фибоначчи. В этих случаях использование функций позволяет эффективно работать с теоретически бесконечными последовательностями, не загружая их в память целиком.
Использование генераторов предоставляет несколько ключевых преимуществ. Так как значения генерируются по одному, не нужно хранить все элементы коллекции в оперативной памяти. Это особенно важно при обработке больших файлов или наборов данных. При этом он сам реализует метод __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 который является генератором. Асинхронные генераторы идеально подходят для работы с сетевыми запросами, так как они позволяют обрабатывать ответ от сервера по мере его поступления.