我已经在CPython中读过,解释器堆栈(调用到达这一点的Python函数列表)与C堆栈(在解释器自己的代码中调用的C函数列表)混合在一起。如果是这样,那么生成器和协程如何实现?他们如何记住自己的执行状态? CPython是否将每个生成器/ coroutine的堆栈复制到OS堆栈中?或者CPython是否只是将生成器的最顶层堆栈帧保留在堆上,因为生成器只能从最顶层的帧生成?
答案 0 :(得分:46)
Python正在运行的Python程序中的堆栈和C堆栈混合的概念可能会产生误导。
Python堆栈与解释器使用的实际C堆栈完全分开。 Python堆栈上的数据结构实际上是完整的Python“框架”对象(甚至可以进行内省并在运行时更改某些属性)。这个堆栈由Python虚拟机管理,它本身在C中运行,因此具有正常的C程序,机器级别,堆栈。
当使用生成器和迭代器时,解释器只是将相应的帧对象存储在除Python程序堆栈之外的其他地方,并在生成器恢复执行时将其推回到那里。这个“其他地方”就是生成器对象本身。在生成器对象上调用“next”或“send”方法会导致这种情况发生。
答案 1 :(得分:16)
yield
指令将当前执行的上下文作为闭包,并将其转换为自己的生活对象。此对象具有__iter__
方法,该方法将在此yield语句之后继续。
因此调用堆栈被转换为堆对象。