Я читал, что в CPython стеки интерпретатора (список функций Python, вызываемых для достижения этой точки) смешиваются с стеком C (список функций C, которые вызывались в собственном коде интерпретатора). Если да, то как реализуются генераторы и сопрограммы? Как они помнят свое состояние исполнения? CPython копирует каждый стек генератора/сопрограммы в стек и из стека ОС? Или CPython просто удерживает верхний стек стека генератора в куче, поскольку генератор может работать только с самого верхнего кадра?
Как генераторы и сопрограммы реализованы в CPython?
Ответ 1
Команда yield
принимает текущий исполняемый контекст как замыкание и преобразует его в собственный объект жизни. Этот объект имеет метод __iter__
, который будет продолжен после этой инструкции yield.
Таким образом, стек вызовов преобразуется в объект кучи.
Ответ 2
Понятие о том, что стек Python и стек C в запущенной программе Python смешиваются, может вводить в заблуждение.
Стек Python является чем-то полностью разделенным, чем фактический стек C, используемый интерпретатором. Структуры данных в стеке Python на самом деле являются полными "фреймовыми" объектами Python (которые даже могут быть интроспекрованы и иметь некоторые атрибуты, измененные во время выполнения). Этот стек управляется виртуальной машиной Python, которая сама запускается на C и, следовательно, имеет обычную C-программу, уровень машины, стек.
При использовании генераторов и итераторов интерпретатор просто сохраняет соответствующий объект фрейма где-то еще, чем в стеке программы Python, и отталкивает его туда, когда выполнение генератора возобновляется. Это "где-то еще" является самим объектом-генератором. Запуск метода "следующий" или "отправка" на объект-генератор вызывает это.
Ответ 3
Несколько существующих ответов и комментариев утверждают, что Python поддерживает "стек программ", который полностью отделен от стека VM C. Это утверждение неверно.
Проверьте ссылку: http://en.wikipedia.org/wiki/Stackless_Python
Stackless Python существует, но не является основным. Понимание - это правильный вопрос.