如何在CPython中实现生成器和协同程序?

A. *_*vis 47 python coroutine

我已经在CPython中读到过,解释器堆栈(调用到达这一点的Python函数列表)与C堆栈(在解释器自己的代码中调用的C函数列表)混合在一起.如果是这样,那么生成器和协同程序是如何实现的呢?他们如何记住自己的执行状态?CPython是否将每个生成器/ coroutine的堆栈复制到OS堆栈中?或者CPython只是将生成器的最顶层堆栈帧保留在堆上,因为生成器只能从最顶层的帧生成?

jsb*_*eno 47

在运行的Python程序中混合使用Python的堆栈和C堆栈这一概念可能会产生误导.

Python堆栈与解释器使用的实际C堆栈完全分开.Python堆栈上的数据结构实际上是完整的Python"框架"对象(甚至可以进行内省,并在运行时更改某些属性).这个堆栈由Python虚拟机管理,它本身在C中运行,因此具有正常的C程序,机器级别,堆栈.

当使用生成器和迭代器时,解释器只是将相应的帧对象存储在除Python程序堆栈之外的其他地方,并在生成器恢复执行时将其推回到那里.这个"其他地方"就是生成器对象本身.在生成器对象上调用"next"或"send"方法会导致这种情况发生.

  • 我在阅读之后查了一下,所以如果有其他人感兴趣的话,这里是[生成器的CPython实现](https://github.com/python/cpython/blob/master/Objects/genobject.c).我建议首先阅读这个答案,它有助于理解代码的作用. (3认同)

Rud*_*udi 17

yield指令将当前执行的上下文作为闭包,并将其转换为自己的生活对象.此对象有一个__iter__方法,该方法将在此yield语句后继续.

因此调用堆栈被转换为堆对象.

  • 重要的是澄清C"硬件"堆栈和Python堆栈是完全不同的东西,因为问题混淆了两者.我的回答澄清了这一点.(@Rudi - 你回答很好,我要留下评论,以便其他人到这里检查那部分) (4认同)