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)这行代码。生成器可以在任何时候被任何函数恢复执行,因为它的栈帧实际上不在栈上而是在堆上。生成器在调用调用层次结构中的位置不是固定的,也不需要遵循常规函数执行时遵循的先进后出顺序。因为这些特性,生成器不仅能用于生成可迭代对象,还可以用于实现多任务协作。

相关推荐
不写八个6 分钟前
Python办公自动化教程(005):Word添加段落
开发语言·python·word
IT学长编程7 分钟前
计算机毕业设计 Java酷听音乐系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·毕业设计·课程设计·毕业论文·音乐系统·计算机毕业设计选题
HEX9CF10 分钟前
【CTF Web】Pikachu xss之href输出 Writeup(GET请求+反射型XSS+javascript:伪协议绕过)
开发语言·前端·javascript·安全·网络安全·ecmascript·xss
IT学长编程24 分钟前
计算机毕业设计 基于协同过滤算法的个性化音乐推荐系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·毕业设计·毕业论文·协同过滤算法·计算机毕业设计选题·个性化音乐推荐系统
小小娥子29 分钟前
Redis的基础认识与在ubuntu上的安装教程
java·数据库·redis·缓存
赵荏苒35 分钟前
Python小白之Pandas1
开发语言·python
几何心凉36 分钟前
已解决:org.springframework.web.HttpMediaTypeNotAcceptableException
java
丶Darling.37 分钟前
代码随想录 | Day26 | 二叉树:二叉搜索树中的插入操作&&删除二叉搜索树中的节点&&修剪二叉搜索树
开发语言·数据结构·c++·笔记·学习·算法
华农第一蒟蒻39 分钟前
Java中JWT(JSON Web Token)的运用
java·前端·spring boot·json·token
两点王爷40 分钟前
使用WebClient 快速发起请求(不使用WebClientUtils工具类)
java·网络