Генераторы в Python: как они это делают? | OTUS
⚡ Подписка на курсы OTUS!
Интенсивная прокачка навыков для IT-специалистов!
Подробнее

Курсы

Программирование
Backend-разработчик на PHP
-9%
Алгоритмы и структуры данных
-9%
Team Lead
-6%
Архитектура и шаблоны проектирования Разработчик IoT
-13%
C# Developer. Professional
-9%
HTML/CSS
-11%
C# ASP.NET Core разработчик
-5%
Kotlin Backend Developer
-8%
iOS Developer. Professional
-8%
Java Developer. Professional JavaScript Developer. Professional Базы данных Android Developer. Professional Framework Laravel Cloud Solution Architecture Highload Architect Reverse-Engineering. Professional Vue.js разработчик Agile Project Manager VOIP инженер Scala-разработчик Супер-практикум по использованию и настройке GIT Symfony Framework Java Developer. Basic Unity Game Developer. Professional Супер-интенсив Azure
Инфраструктура
Экспресс-курс «IaC Ansible»
-10%
Administrator Linux.Basic
-10%
Мониторинг и логирование: Zabbix, Prometheus, ELK
-10%
Экспресс-курс «CI/CD или Непрерывная поставка с Docker и Kubernetes»
-30%
Administrator Linux. Professional
-6%
Дизайн сетей ЦОД
-13%
NoSQL Основы Windows Server MS SQL Server Developer Инфраструктурная платформа на основе Kubernetes Cloud Solution Architecture Highload Architect Разработчик голосовых ассистентов и чат-ботов VOIP инженер Супер-практикум по работе с протоколом BGP Супер - интенсив по паттернам проектирования Супер - интенсив по Kubernetes Супер-интенсив "Tarantool"
Специализации Курсы в разработке Подготовительные курсы
+7 499 938-92-02

Генераторы в Python: как они это делают?

Python_Deep_24-5020-f0d538.09_site.png

Все мы знаем и любим генераторы в Python. По сути, генератор – это итератор, который можно использовать в цикле, как обычно. Но генератор дополнительно содержит внутри ключевое слово yield.

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

Но, чёрт, как он это делает?

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

Во время вызова next(gen_object) вызывается PyEval_EvalFrame для текущего execution frame’а. Это одна из самых главных функций интерпретатора: внутри она, в том числе, знает про ключевое слово yield:

TARGET(YIELD_VALUE) {
    retval = POP();
    f->f_stacktop = stack_pointer;
    why = WHY_YIELD;
    goto fast_yield;
}

В данном случае возвращается значение, а текущий фрейм сохраняется (f->f_stacktop = stack_pointer), так что после следующего next’а можно продолжить там, где остановились, ведь PyEval_EvalFrame будет вызван на том же фрейме, что и раньше, с тем же стеком и состоянием. В обычных функциях f_stacktop приравнивается к NULL.

Есть вопрос? Напишите в комментариях!

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

Автор
0 комментариев
Для комментирования необходимо авторизоваться