По сути, генератор - это итератор, который можно использовать в цикле, как обычно, но генератор дополнительно содержит внутри ключевое слово yield. После каждого yield генератор временно прекращает исполнение и возвращает управление, при следующем вызове стартуя с того места, где закончил в прошлый раз, при этом сохраняя состояние и значения переменных между вызовами. Но, черт побери, как он это делает?Объект генератор, помимо всего прочего, содержит в себе указатель на текущий execution frame, который в свою очередь содержит стек вызова для данного генератора. Во время вызова next(gen_object) вызывается PyEval_EvalFrame для текущего execution frame’а. Это одна из самых главных функций интерпретатора, внутри, она, в том числе, знает про ключевое слово yieldTARGET(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.Проверь свои знания Python прямо сейчас! http://otus.ru/lessons?course=3?utm_source=ok&utm_medium=internal&utm_campaign=deeppython03.07
Присоединяйтесь — мы покажем вам много интересного
Присоединяйтесь к ОК, чтобы подписаться на группу и комментировать публикации.
Нет комментариев