Как интерпретатор Python реализует сопрограмму - PullRequest
0 голосов
/ 20 февраля 2019

В настоящее время я пытаюсь понять, как Python реализует yield и генераторы.В документации сказано:

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

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

И последний вопрос заключается в том, существует ли какой-либо алгоритм для получения реализации итератора генератора из произвольной функции генератора.Например, предположим, что у нас есть функция генератора:

def generator_f():
    for i in range(10):
        yield i
    for i in range(10):
        yield i

Можем ли мы систематически реализовать итератор, функционально эквивалентный итератору генератора, возвращаемому generator_f()?Функционально я имею в виду как поведение, так и эффективность (памяти).

1 Ответ

0 голосов
/ 20 февраля 2019

Вы можете увидеть, как Cpython реализует сопрограммы здесь, в cpython/Lib/asyncio/coroutines.py.Чтобы увидеть, как реализованы генераторы, см. cpython/Objects/genobject.c.В частности, логика yield from находится в функциях gen_getyieldfrom() и _PyGen_yf().

По поводу вашего вопроса об эквивалентном итераторе:

iter([*range(10), *range(10)])
...