python代码自动生成器原理 python 生成器原理

python生成器原理剖析

函数的调用满足“后进先出”的原则,也就是说,最后被调用的函数应该第一个返回,函数的递归调用就是一个经典的例子。显然,内存中以“后进先出”"方式处理数据的栈段是最适合用于实现函数调用的载体,在编译型程序语言中,函数被调用后,函数的参数,返回地址,寄存器值等数据会被压入栈,待函数体执行完毕,将上述数据弹出栈。这也意味着,一个被调用的函数一旦执行完毕,它的生命周期就结束了。

在python这样的解释型语言中,函数的调用也是依赖栈的。之前说过,pvthon的标准解释器是用C写的。解释器用-个叫做PyEval EvalFrameEx的C函数来执行python程序。对于一个python中的函数,解释器接受一个python的栈帧对象,并在这个栈帧的上下文中执行python字节码。

我们来看看这样一个例子:

我们用dis模块可以查看python程序的字节码,下面是函数f00()的字节码:

fo0函数将bar加载到栈中并调用它,然后从栈中弹出返回值,最后加载并返回None,当PyEval EvalFrameEx遇到CALL FUNCTION字节码的时候,它会创建一个新的python栈帧,然后用这个新的帧作为参数递归调用PyEval EValFrameEx来执行bar。不过有一点要注意的是,python解释器是个普通的C程序,所以它的堆栈帧就是普通的堆栈。但是它操作的pvthon堆栈帧是分配在堆上的,所以pvthon的栈帧可以在它的调用之外存活。而且可以显式的保存下来。

这是python生成器的技术基础,下面是一个生成器:

返回的结果是:

调用gen()产生的所有生成器都指向同一个代码对象,但是每个都有自己的堆栈帧。这个堆栈帧并不存在于实际的堆栈上,它在堆内存上等待着被使用。

堆栈帧有个"last instruction”指针,指向最近执行的那条指令。刚开始的时候last instruction指针是-1意味着生成器尚未开始,这就是为什么上面的例子中有next(a)这行代码。生成器可以在任何时候被任何函数恢复执行,因为它的栈帧实际上不在栈上而是在堆上。生成器在调用调用层次结构中的位置不是固定的,也不需要遵循常规函数执行时遵循的先进后出顺序。因为这些特性,生成器不仅能用于生成可迭代对象,还可以用于实现多任务协作。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值