python yield,到这个层次,才能叫深入哈
2024-09-02 20:57:59
http://python.jobbole.com/88677/?utm_source=blog.jobbole.com&utm_medium=relatedPosts
~~~~~~~~~~~~~~~~~~~~~~
划重点:
当 PyEval_EvalFrameEx 遇到 CALL_FUNCTION 字节码的时候,它会创建一个新的 Python 堆栈帧,然后用这个新的帧作为参数递归调用 PyEval_EvalFrameEx 来执行 bar。
Python 的堆栈帧是分配在堆内存中的,理解这一点非常重要!Python 解释器是个普通的 C 程序,所以它的堆栈帧就是普通的堆栈。但是它操作的 Python 堆栈帧是在堆上的。除了其他惊喜之外,这意味着 Python 的堆栈帧可以在它的调用之外存活。(FIXME: 可以在它调用结束后存活)。
生成器可以在任何时候被任何函数恢复执行,因为它的堆栈帧实际上不在堆栈上——它在堆(内存)上。生成器在调用调用层次结构中的位置不是固定的,它不需要遵循常规函数执行时遵循的先进后出顺序。生成器被是被解放了的,它像云一样浮动。
1,解释器执行到 yield 后,取出栈中的最后的元素返回
2,yield 直接跳到了 fast_yield,跳过了正常函数返回的部分,也就是跳过了清理函数现场,这样下次执行的时候才能从返回的地方开始,而不是重现开始执行
PyObject * PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) { ... case YIELD_VALUE: retval = POP(); f->f_stacktop = stack_pointer; why = WHY_YIELD; goto fast_yield; ... assert(why != WHY_YIELD); /* Pop remaining stack entries. */ while (!EMPTY()) { v = POP(); Py_XDECREF(v); } if (why != WHY_RETURN) retval = NULL; fast_yield: ... /* pop frame */ exit_eval_frame: Py_LeaveRecursiveCall(); tstate->frame = f->f_back; return retval; }
static PyObject * gen_send_ex(PyGenObject *gen, PyObject *arg, int exc) { PyThreadState *tstate = PyThreadState_GET(); PyFrameObject *f = gen->gi_frame; PyObject *result; ... /* Push arg onto the frame's value stack */ result = arg ? arg : Py_None; Py_INCREF(result); *(f->f_stacktop++) = result; } /* Generators always return to their most recent caller, not * necessarily their creator. */ Py_XINCREF(tstate->frame); assert(f->f_back == NULL); f->f_back = tstate->frame; gen->gi_running = ; result = PyEval_EvalFrameEx(f, exc); gen->gi_running = ; ... return result; }
可以看到 send 做的事情:
1,把传入的参数放到栈顶
2,执行 frame
3,返回执行的结果
最新文章
- React构建单页应用方法与实例
- PHP正则表达式模式修饰符详解
- RequireJS实例分析
- mongo链接报错:couldn't connect to server 127.0.0.1:27017 (127.0.0.1)
- SpringMvc:处理模型数据
- Binary Tree Level Order Traversal [LeetCode]
- Unity动态加载和内存管理(三合一)
- android 随手记 广播通知栏 二
- 利用js加载本地图片预览功能
- AlarmReceiver 与IntentService的使用
- MYSQL 时间计算的 3 种函数
- 字符集 ISO-8859-1(3)
- loj#6074. 「2017 山东一轮集训 Day6」子序列(矩阵乘法 dp)
- 「Link-Cut Tree」学习笔记
- CSS——nth-child()
- 25个SSH命令
- 算法(第四版)C# 习题题解——1.1
- Python-HTML基础
- C# 在网页中将Base64编码的字符串显示成图片
- 谈谈如何优化MYSQL数据库查询
热门文章
- PHP7 学习笔记(十)会话控制
- FastReport.Net报表故障排除方法
- 【原创】angularjs1.3.0源码解析之执行流程
- Ribbon实现Office开始菜单
- MySQL5.7使用错误解决:ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)【取消或重设root密码】
- 给父元素与子元素分别设置visibility注意点
- break case
- 2017-2018-2 20155303『网络对抗技术』Exp9:Web安全基础
- SpringBoot集成Dubbo
- python 历险记(一)— python 的String,集合(List,元组,Dict)