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入门篇之面向对象
Oct 20 Python
Python内置函数 next的具体使用方法
Nov 24 Python
django 按时间范围查询数据库实例代码
Feb 11 Python
Django管理员账号和密码忘记的完美解决方法
Dec 06 Python
Python设计模式之建造者模式实例详解
Jan 17 Python
对python pandas读取剪贴板内容的方法详解
Jan 24 Python
解决python 3 urllib 没有 urlencode 属性的问题
Aug 22 Python
基于python进行抽样分布描述及实践详解
Sep 02 Python
python3正则模块re的使用方法详解
Feb 11 Python
Python在终端通过pip安装好包以后在Pycharm中依然无法使用的问题(三种解决方案)
Mar 10 Python
Python基于time模块表示时间常用方法
Jun 18 Python
matplotlib阶梯图的实现(step())
Mar 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简单统计字符串单词数量的方法
2015/06/19 PHP
PHP检测接口Traversable用法详解
2017/12/29 PHP
TP5框架安全机制实例分析
2020/04/05 PHP
5 cool javascript apps
2007/03/24 Javascript
javascript面向对象编程代码
2011/12/19 Javascript
js网页版计算器的简单实现
2013/07/02 Javascript
JS增加行复制行删除行的实现代码
2013/11/09 Javascript
基于jQuery实现点击最后一行实现行自增效果的表格
2016/01/12 Javascript
微信小程序 常见问题总结(4058,40013)及解决办法
2017/01/11 Javascript
Angular2使用Angular-CLI快速搭建工程(二)
2017/05/21 Javascript
Kotlin学习第一步 kotlin语法特性
2017/05/25 Javascript
详解小程序原生使用ES7 async/await语法
2018/08/06 Javascript
简单了解JavaScript作用域
2020/07/31 Javascript
js+css3实现炫酷时钟
2020/08/18 Javascript
[59:42]Secret vs Alliacne 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/17 DOTA
[01:46]新英雄登场
2019/09/10 DOTA
Python入门篇之条件、循环
2014/10/17 Python
浅谈Python的异常处理
2016/06/19 Python
python3中替换python2中cmp函数的实现
2019/08/20 Python
Python进程池Pool应用实例分析
2019/11/27 Python
Python unittest生成测试报告过程解析
2020/09/08 Python
Python通过递归函数输出嵌套列表元素
2020/10/15 Python
python的数学算法函数及公式用法
2020/11/18 Python
Bogner美国官网:滑雪服中的”Dior”
2018/01/30 全球购物
Skyscanner香港:机票比价, 平机票和廉价航空机票预订
2020/02/07 全球购物
学期自我鉴定范文
2013/10/01 职场文书
实习老师离校感言
2014/02/03 职场文书
称象教学反思
2014/02/03 职场文书
护校行动方案
2014/05/31 职场文书
防灾减灾标语
2014/10/07 职场文书
学生个人总结范文
2015/02/15 职场文书
2015年打非治违工作总结
2015/04/02 职场文书
pytorch Dropout过拟合的操作
2021/05/27 Python
Python数据可视化之用Matplotlib绘制常用图形
2021/06/03 Python
Python Pandas模块实现数据的统计分析的方法
2021/06/24 Python
mysql 获取时间方式
2022/03/20 MySQL