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 相关文章推荐
wxPython窗口中文乱码解决方法
Oct 11 Python
Python的“二维”字典 (two-dimension dictionary)定义与实现方法
Apr 27 Python
python中使用PIL制作并验证图片验证码
Mar 15 Python
python 读取摄像头数据并保存的实例
Aug 03 Python
python3调用百度翻译API实现实时翻译
Aug 16 Python
Python过滤txt文件内重复内容的方法
Oct 21 Python
Python XlsxWriter模块Chart类用法实例分析
Mar 11 Python
PyQt5 QTable插入图片并动态更新的实例
Jun 18 Python
Python 异步协程函数原理及实例详解
Nov 13 Python
python高级特性简介
Aug 13 Python
安装pyinstaller遇到的各种问题(小结)
Nov 20 Python
python函数的两种嵌套方法使用
Apr 02 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常用字符串的总结(待续)
2013/06/07 PHP
PHP使用Alexa API获取网站的Alexa排名例子
2014/06/12 PHP
使用WordPress发送电子邮件的相关PHP函数用法解析
2015/12/15 PHP
laravel 解决路由除了根目录其他都404的问题
2019/10/18 PHP
firefox中JS读取XML文件
2006/12/21 Javascript
innertext , insertadjacentelement , insertadjacenthtml , insertadjacenttext 等区别
2007/06/29 Javascript
高效的表格行背景隔行变色及选定高亮的JS代码
2010/12/04 Javascript
javascript各浏览器中option元素的表现差异
2011/04/07 Javascript
关于跨站脚本攻击问题
2011/12/22 Javascript
javascript 正则表达式相关应介绍
2012/11/27 Javascript
优化Jquery,提升网页加载速度
2013/11/14 Javascript
jquery.post用法关于type设置问题补充
2014/01/03 Javascript
多种js图片预加载实现方式分享
2016/02/19 Javascript
JS实现拼图游戏
2021/01/29 Javascript
[03:55]DOTA2完美大师赛选手传记——LFY.MONET
2017/11/18 DOTA
python基于xml parse实现解析cdatasection数据
2014/09/30 Python
python读取图片任意范围区域
2019/01/23 Python
python用opencv批量截取图像指定区域的方法
2019/01/24 Python
python实现银联支付和支付宝支付接入
2019/05/07 Python
python实现横向拼接图片
2020/03/23 Python
python中reload重载实例用法
2020/12/15 Python
美国最大的宠物药店:1-800-PetMeds
2016/10/02 全球购物
英国创新设计文具、卡片和礼品包装网站:Paperchase
2018/07/14 全球购物
美国儿童珠宝在线零售商:Loveivy
2019/05/22 全球购物
实习期自我鉴定
2013/10/11 职场文书
人事文员岗位职责
2014/02/16 职场文书
俄语专业职业生涯规划
2014/02/26 职场文书
机关节能减排实施方案
2014/03/17 职场文书
五一口号
2014/06/19 职场文书
2014年语文教师工作总结
2014/12/18 职场文书
先进事迹材料范文
2014/12/29 职场文书
小升初自荐信怎么写
2015/03/26 职场文书
2019年暑期法院实习报告
2019/12/18 职场文书
2019年中学生的思想品德评语集锦
2019/12/19 职场文书
Python帮你解决手机qq微信内存占用太多问题
2022/02/15 Python
MySQL数据库 安全管理
2022/05/06 MySQL