Python函数生成器原理及使用详解


Posted in Python onMarch 12, 2020

1.python函数运行原理

import inspect
frame = None
def foo():
  bar()


def bar():
  global frame
  frame = inspect.currentframe()
  pass

# python解释器 python.exe 会用一个叫做PyEval_EvalFrameEx(c语言函数)去执行foo函数,首先会创建一个栈帧(stack frame),
"""
python在运行前会编译成字节码对象
当foo调用bar函数进,又会创建一个栈帧,
关键是所有的栈帧都是分配在堆内存, 堆内存有个特点,不手动释放,就会一直存在
这就决定了栈帧可以独立于调用者存在.

"""

# import dis
# print(dis.dis(foo)) # 查看foo函数的字节码


foo() #先调用一下foo函数 ,这个frame就有值.

print(frame.f_code.co_name) # bar  查看这个栈帧, bar 所以还是可以拿到bar的栈帧,然后就可以调用bar函数

caller_frame = frame.f_back # 当前frame栈帧的调用者的栈帧
print(caller_frame.f_code.co_name) # foo , 也可以拿到bar函数的栈帧

python中函数的调用就是创建栈帧的过程,而这些创建的栈帧都是存放在堆上面,不释放就永久存在,所以我们拿到每个函数对应的栈帧,就可以调用这个函数.

java就不行了,函数执行完毕,直接弹栈完蛋.

Python函数生成器原理及使用详解

2.生成器执行原理

测试代码

def gen_fun():
  yield 1
  name = 'admin'
  yield 2
  gender = 'male'
  return 3

看看测试代码对应的字节码文件

0 LOAD_CONST        1 (1)
YIELD_VALUE
POP_TOP
     6 LOAD_CONST        2 ('admin')
STORE_FAST        0 (name)
     10 LOAD_CONST        3 (2)
YIELD_VALUE
POP_TOP
     16 LOAD_CONST        4 ('male')
STORE_FAST        1 (gender)
     20 LOAD_CONST        5 (3)
RETURN_VALUE
None

测试gi_frame

# 在没有执行生成器时
print(gen.gi_frame.f_lasti) # -1 ,在没有调用next方法迭代时,f_lasti 等于-1, 表示还没开始呢
print(gen.gi_frame.f_locals) # {}

# 执行第一行
next(gen)

print(gen.gi_frame.f_lasti) # 2  # 执行一行next后,代码停在了第二行,看上面字节码文件
print(gen.gi_frame.f_locals) # {}

# 再执行一次
next(gen)

print(gen.gi_frame.f_lasti) # 12 # 又执行一次next之后,程序停在了12行
print(gen.gi_frame.f_locals) # {'name': 'admin'}

由上面的测试代码可以知道,在生成器的gi_frame对象中维护着两个重要的属性f_lasti和f_locals.

f_lasti记录着当前代码运行到哪一行了(注意这里的那一行是指编译之后的字节码文件)

f_locals维护着当前生成器中的属性字段

有了这两个属性,生成器就知道下一次next从哪儿开始执行了....

Python函数生成器原理及使用详解

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
使用python解析xml成对应的html示例分享
Apr 02 Python
python模拟鼠标拖动操作的方法
Mar 11 Python
Python制作数据导入导出工具
Jul 31 Python
python Django批量导入数据
Mar 25 Python
Python 中包/模块的 `import` 操作代码
Apr 22 Python
从列表或字典创建Pandas的DataFrame对象的方法
Jul 06 Python
为什么从Python 3.6开始字典有序并效率更高
Jul 15 Python
Python 转换文本编码实现解析
Aug 27 Python
PageFactory设计模式基于python实现
Apr 14 Python
Python自动发送和收取邮件的方法
Aug 12 Python
浅谈Python列表嵌套字典转化的问题
Apr 07 Python
Python可视化学习之seaborn绘制矩阵图详解
Feb 24 Python
python deque模块简单使用代码实例
Mar 12 #Python
python中安装django模块的方法
Mar 12 #Python
python3 sorted 如何实现自定义排序标准
Mar 12 #Python
Python dict和defaultdict使用实例解析
Mar 12 #Python
Python数据结构dict常用操作代码实例
Mar 12 #Python
Python基于类路径字符串获取静态属性
Mar 12 #Python
对python中return与yield的区别详解
Mar 12 #Python
You might like
用PHP读取RSS feed的代码
2008/08/01 PHP
php addslashes 函数详细分析说明
2009/06/23 PHP
PHP里的中文变量说明
2011/07/23 PHP
php制作基于xml的RSS订阅源功能示例
2017/02/08 PHP
javascript Xml增删改查(IE下)操作实现代码
2009/01/30 Javascript
javaScript Array(数组)相关方法简述
2009/07/25 Javascript
event.currentTarget与event.target的区别介绍
2012/12/31 Javascript
javascript实现瀑布流自适应遇到的问题及解决方案
2015/01/28 Javascript
JavaScript函数参数使用带参数名的方式赋值传入的方法
2015/03/19 Javascript
如何在JS中实现相互转换XML和JSON
2016/07/19 Javascript
AngularJS报错$apply already in progress的解决方法分析
2017/01/30 Javascript
javascript基本数据类型和转换
2017/03/17 Javascript
zTree实现节点修改的实时刷新功能
2017/03/20 Javascript
JavaScript中offsetWidth的bug及解决方法
2017/05/17 Javascript
angular学习之从零搭建一个angular4.0项目
2017/07/10 Javascript
基于vue实现一个神奇的动态按钮效果
2019/05/15 Javascript
uni-app如何实现增量更新功能
2020/01/03 Javascript
jquery实现垂直手风琴菜单
2020/03/04 jQuery
Js生成随机数/随机字符串的方法小结【5种方法】
2020/05/27 Javascript
Python字符串详细介绍
2015/05/09 Python
浅谈python常用程序算法
2019/03/22 Python
Python基础知识点 初识Python.md
2019/05/14 Python
CSS3实现的渐变幻灯片效果
2020/12/07 HTML / CSS
法国足球商店:Footcenter
2019/07/06 全球购物
金融专业应届生求职信
2013/11/02 职场文书
幼儿园毕业园长感言
2014/02/24 职场文书
《奇妙的国际互联网》 教学反思
2014/02/25 职场文书
2014全国两会心得体会
2014/03/17 职场文书
大学生个人求职信例文
2014/07/07 职场文书
银行奉献演讲稿
2014/09/16 职场文书
2014党员学习兰辉先进事迹思想汇报
2014/09/17 职场文书
房屋认购协议书
2015/01/29 职场文书
餐厅服务员岗位职责
2015/02/09 职场文书
硕士毕业答辩开场白
2015/05/27 职场文书
导游词之秦皇岛燕塞湖
2020/01/03 职场文书
i5-10400f处理相当于i7多少水平
2022/04/19 数码科技