python 生成器 原理_python中生成器的工作原理

Any function contains a yield statement will return a generator object

这是正确的。包含yield的函数的返回值是生成器对象。generator对象是一个迭代器,其中每个迭代都返回一个从支持生成器的代码中yield的值。在A generator object is a stack contains state

生成器对象包含一个指向当前执行帧的指针,以及用于维护生成器状态的一大堆其他内容。执行框架包含生成器中代码的调用堆栈。在Each time I call .next method Python extracts the function's state and

when it finds another yield statement it'll bind the state again and

deletes the prior state

差不多吧。{{cd3}你调用^时:gen_send_ex(PyGenObject *gen, PyObject *arg, int exc) { // This is called when you call next(gen_object)

PyFrameObject *f = gen->gi_frame;

...

gen->gi_running = 1;

result = PyEval_EvalFrameEx(f, exc); // This evaluates the current frame

gen->gi_running = 0;PyObject* PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)

This is the main, unvarnished function of Python interpretation. It is

literally 2000 lines long. The code object associated with the

execution frame f is executed, interpreting bytecode and executing

calls as needed. The additional throwflag parameter can mostly be

ignored - if true, then it causes an exception to immediately be

thrown; this is used for the throw() methods of generator objects.

当您放弃时,帧的值堆栈的当前值将保持不变(通过f->f_stacktop = stack_pointer),这样当再次调用next时,我们可以恢复到上次停止的位置。所有非生成器函数在完成求值后将f_stacktop设置为NULL。因此,当您在generator对象上再次调用next时,PyEval_ExvalFrameEx将再次被调用,使用与之前相同的帧指针。指针的状态将与上一次生成时完全相同,因此将从该点继续执行。实际上,帧的当前状态是“冻结”。这在PEP that introduced generators中描述:If a yield statement is encountered, the state of the function is

frozen, and the value [yielded] is returned to .next()'s

caller. By "frozen" we mean that all local state is retained,

including the current bindings of local variables, the instruction

pointer, and the internal evaluation stack: enough information is

saved so that the next time .next() is invoked, the function can

proceed exactly as if the yield statement were just another external

call.

以下是生成器对象维护的大多数状态(直接从其头文件获取):typedef struct {

PyObject_HEAD

/* The gi_ prefix is intended to remind of generator-iterator. */

/* Note: gi_frame can be NULL if the generator is "finished" */

struct _frame *gi_frame;

/* True if generator is being executed. */

char gi_running;

/* The code object backing the generator */

PyObject *gi_code;

/* List of weak reference. */

PyObject *gi_weakreflist;

/* Name of the generator. */

PyObject *gi_name;

/* Qualified name of the generator. */

PyObject *gi_qualname;

} PyGenObject;

gi_frame是指向当前执行帧的指针。在

请注意,所有这些都是特定于CPython实现的。PyPy/Jython/etc.很可能以完全不同的方式实现生成器。我鼓励您read through the source for generator objects来了解更多关于CPython实现的信息。在

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值