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,返回执行的结果

python yield,到这个层次,才能叫深入哈的更多相关文章

  1. Python yield与实现

    Python yield与实现  yield的功能类似于return,但是不同之处在于它返回的是生成器. 生成器 生成器是通过一个或多个yield表达式构成的函数,每一个生成器都是一个迭代器(但是迭 ...

  2. 【转】Python yield 使用浅析

    转载地址: www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/ Python yield 使用浅析 初学 Python 的开发者经 ...

  3. Python yield 使用浅析(转)

    Python yield 使用浅析 初学 Python 的开发者经常会发现很多 Python 函数中用到了 yield 关键字,然而,带有 yield 的函数执行流程却和普通函数不一样,yield 到 ...

  4. python yield from 语法

    python yield from 语法 yield语法比较简单, 教程也很多 , yield from的中文讲解很少 , python官网是这样解释的 PEP 380 adds the yield ...

  5. python yield用法 (tornado, coroutine)

    yield关键字用来定义生成器(Generator),其具体功能是可以当return使用,从函数里返回一个值,不同之处是用yield返回之后,可以让函数从上回yield返回的地点继续执行.也就是说,y ...

  6. python yield 与 yield from转

    python yield 与 yield from转 https://blog.csdn.net/chenbin520/article/details/78111399?locationNum=7&a ...

  7. python 中几个层次的中文编码.md

    转自:[http://swj.me/] 介绍 一直不太喜欢使用命令行,所以去年年底的技术创新中,使用TkInter来开发小工具.结果花费了大量的时间来学习TkInter ui的使用. 最近想整理该工具 ...

  8. 转:Python yield 使用浅析 from IBM Developer

    评注:没有看懂. 转: https://www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/ Python yield 使用浅析 初 ...

  9. python yield关键词使用总结

    python yield关键词使用总结 by:授客 QQ:1033553122 测试环境 win10 python 3.5 yield功能简介 简单来说,yield 的作用就是把一个函数变成一个 ge ...

  10. Python yield 使用浅析【转】

    Python yield 使用浅析 IBM developerWorks 中国 : Open source IBM 开源 - IBM Developer 中国 (原 developerWorks 中国 ...

随机推荐

  1. Study 3 —— Python运算符

    参考资料:http://www.runoob.com/python/python-operators.html#ysf2 定义变量: a = 10, b = 20 算术运算符: 运算符   描述 实例 ...

  2. Said

    呃~~生活中的每天都会经历很多事儿,而影响结果的无非就是人对事物的处理方式和对事物的处理态度~~ 在上学期间,有时考试不理想,我都会进行反思,对不该错的题巩固在三,对不会做的题查缺补漏……因为不能不思 ...

  3. PHP7 学习笔记(九)phpsize动态编译openssl扩展 (微信公众平台)

    先吐槽,微信公众平台授权出问题了,尽然访问不了 一.问题描述: 使用PHP中的库函数file_get_contents时出现Unable to find the wrapper "https ...

  4. 将文本(lrc,txt)文件转换成UTF-8格式

    UTF-8是UNICODE的一种变长字符编码又称万国码,由Ken Thompson于1992年创建.现在已经标准化为RFC 3629.UTF-8用1到6个字节编码UNICODE字符.用在网页上可以同一 ...

  5. 转 -- 详解python的super()的作用和原理

    原文地址 Python中对象方法的定义很怪异,第一个参数一般都命名为self(相当于其它语言的this),用于传递对象本身,而在调用的时候则不必显式传递,系统会自动传递. 今天我们介绍的主角是supe ...

  6. CSS魔法(三)浮动、相对定位、绝对定位

    浮动 为何需要浮动? 浮动float最开始出现的意义是为了让文字环绕图片而已,但人们发现,如果想要三个块级元素并排显示,都给它们加个float来得会比较方便. 浮动问题? 为何要清除浮动? 很多情况下 ...

  7. VS复制文件到输出目录

    1.选中项目文件 2. 3.编译时就会自动创建目录,并复制文件

  8. mysql案例 ~ 主从复制延迟处理(3)

    一 简介:今天咱们来汇总下如何避免主从延迟 二 方案: 1 集群硬件配置统一,磁盘组更好(SSD最佳),更大的内存 2 linux系统+mysql的配置参数已经优化 3 mysql从库没有任何慢语句进 ...

  9. DSO windowed optimization 代码 (1)

    这里不想解释怎么 marginalize,什么是 First-Estimates Jacobian (FEJ).这里只看看代码,看看Hessian矩阵是怎么构造出来的. 1 优化流程 整个优化过程,也 ...

  10. Java编程:悲观锁、乐观锁的区别及使用场景

    定义: 悲观锁(Pessimistic Lock): 每次获取数据的时候,都会担心数据被修改,所以每次获取数据的时候都会进行加锁,确保在自己使用的过程中数据不会被别人修改,使用完成后进行数据解锁.由于 ...