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 bsddb模块操作Berkeley DB数据库介绍
Apr 08 Python
理解Python垃圾回收机制
Feb 12 Python
Python实现的在特定目录下导入模块功能分析
Feb 11 Python
django框架模型层功能、组成与用法分析
Jul 30 Python
Python使用python-docx读写word文档
Aug 26 Python
Python使用matplotlib实现交换式图形显示功能示例
Sep 06 Python
Django实现文件上传和下载功能
Oct 06 Python
python求绝对值的三种方法小结
Dec 04 Python
python代码如何注释
Jun 01 Python
python 实时调取摄像头的示例代码
Nov 25 Python
Python中Cookies导出某站用户数据的方法
May 17 Python
Python OpenCV形态学运算示例详解
Apr 07 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
基于PHPExcel的常用方法总结
2013/06/13 PHP
php 使用GD库为页面增加水印示例代码
2014/03/24 PHP
关于laravel模板中生成URL的几种模式总结
2019/10/18 PHP
解决windows上php xdebug 无法调试的问题
2020/02/19 PHP
通过location.replace禁止浏览器后退防止重复提交
2014/09/04 Javascript
JS实现的4种数字千位符格式化方法分享
2015/03/02 Javascript
JavaScript动态修改网页元素内容的方法
2015/03/21 Javascript
javascript常用功能汇总
2015/07/05 Javascript
JavaScript的模块化开发框架Sea.js上手指南
2016/05/12 Javascript
原生JS实现的轮播图功能详解
2018/08/06 Javascript
在Vue项目中引入JQuery-ui插件的讲解
2019/01/27 jQuery
vue+element 模态框表格形式的可编辑表单实现
2019/06/07 Javascript
微信小程序tabBar 返回tabBar不刷新页面
2019/07/25 Javascript
jquery+css3实现的经典弹出层效果示例
2020/05/16 jQuery
[01:19:46]EG vs Secret 2019国际邀请赛淘汰赛 胜者组 BO3 第二场 8.21.mp4
2020/07/19 DOTA
Python中函数及默认参数的定义与调用操作实例分析
2017/07/25 Python
python2 与python3的print区别小结
2018/01/16 Python
python实现连连看辅助之图像识别延伸
2019/07/17 Python
Flask框架模板继承实现方法分析
2019/07/31 Python
python爬虫豆瓣网的模拟登录实现
2019/08/21 Python
python实现按首字母分类查找功能
2019/10/31 Python
Python+Kepler.gl实现时间轮播地图过程解析
2020/07/20 Python
海淘母婴商城:国际妈咪
2016/07/23 全球购物
给实习单位的感谢信
2014/02/01 职场文书
签约仪式主持词
2014/03/19 职场文书
中文专业毕业生自荐信
2014/05/24 职场文书
治安消防安全责任书
2014/07/23 职场文书
九一八事变演讲稿范文
2014/09/14 职场文书
城市轨道交通工程职业生涯规划书范文
2014/09/16 职场文书
幼儿教师自我剖析材料
2014/09/29 职场文书
群众路线个人剖析材料及整改措施
2014/11/04 职场文书
通用员工手册范本
2015/05/14 职场文书
小区物业管理2015年度工作总结
2015/10/22 职场文书
2016高校自主招生自荐信范文
2016/01/28 职场文书
100句拼搏进取的名言警句,值得一读!
2019/10/07 职场文书
2019年市场部个人述职报告(三篇)
2019/10/23 职场文书