发电机功能如何在内部工作?

ove*_*nge 2 python generator

下面是一个发电机功能.

def f():
   x=1
   while 1:
      y = yield x
      x += y
Run Code Online (Sandbox Code Playgroud)

这个生成器function(f)是否在内部实现,如下所示?

class f(collections.Iterable):
   def __init__(self):
      self.x = 1
   def __iter__(self):
      return iter(self)
   def __next__(self):
      return self.x
   def send(self, y):
      self.x += y
      return self.next()
Run Code Online (Sandbox Code Playgroud)

编辑:

是我的问题的答案.

Ray*_*ger 12

在内部,生成器的工作方式与常规函数调用大致相同.引擎盖下,运行的发电机和运行功能大多使用相同的机器.

调用函数或生成器时,会创建堆栈帧.它具有局部变量(包括传递给函数的参数),指向活动操作码的代码指针,以及用于挂起的try-blocks,带有块或循环的堆栈.

在常规功能中,立即开始执行.当return遇到,最终的结果保持并通过StackFrame与它所引用的一切一起释放.

生成器函数中,stackframe包装在generator-iterator对象中并立即返回.生成器函数中的代码仅在由next(g)or 调用时运行g.send(v).yield遇到时暂停执行.

想到生成器的一种方法是它们就像可以暂停yield和恢复的函数g.next().堆栈帧保持活动状态,因此恢复正在运行的生成器比创建新函数调用便宜得多,新函数调用必须在每次调用时构建新帧.

  • @overexchange我想您正在想象这比实际情况要复杂。``next(g)``的代码基本上可以归结为``PyEval_EvalFrameEx(gen-> gi_frame,exc)``。就是这样,它只是执行框架的当前状态(请参阅“ Objects / genobject.c”,在Python 2.7中清晰明了)。收益率只是从该调用中返回。相反,函数调用运行``PyEval_EvalCodeEx(...)”,这将创建一个新框架并执行该框架,如上所示。参见``Objects / funcobject.c''。 (4认同)
  • @overexchange生成器和函数的执行都涉及运行当前的操作码和更新代码指针。暂停只是意味着要停止这样做。恢复意味着继续这样做。跟我数1、2、3,现在再谈其他事情,并继续对4、5、6进行表述……您只需要知道最后一个数。同样,堆栈框架保留功能状态,您可以继续停止更新它,也可以随时恢复更新。 (2认同)