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批量下载图片的三种方法
Apr 22 Python
Python比较两个图片相似度的方法
Mar 13 Python
python中requests使用代理proxies方法介绍
Oct 25 Python
Python获取二维矩阵每列最大值的方法
Apr 03 Python
python使用udp实现聊天器功能
Dec 10 Python
Python向excel中写入数据的方法
May 05 Python
python中matplotlib条件背景颜色的实现
Sep 02 Python
django实现类似触发器的功能
Nov 15 Python
深入浅析python变量加逗号,的含义
Feb 22 Python
keras训练浅层卷积网络并保存和加载模型实例
Jul 02 Python
关于Kotlin中SAM转换的那些事
Sep 15 Python
搭建pypi私有仓库实现过程详解
Nov 25 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
BBS(php & mysql)完整版(三)
2006/10/09 PHP
PHP 动态生成静态HTML页面示例代码
2014/01/15 PHP
PHP+Memcache实现wordpress访问总数统计(非插件)
2014/07/04 PHP
PHP中实现接收多个name相同但Value不相同表单数据实例
2015/02/03 PHP
php删除二维数组中的重复值方法
2018/03/12 PHP
用JS控制回车事件的代码
2011/02/20 Javascript
js 动态修改css文件的方法
2014/08/05 Javascript
js实现最短的XML格式化工具实例
2015/03/12 Javascript
javascript获取系统当前时间的方法
2015/11/19 Javascript
JS中创建函数的三种方式及区别
2016/03/13 Javascript
js中遍历Map对象的简单实例
2016/08/08 Javascript
jQuery、layer实现弹出层的打开、关闭功能
2017/06/28 jQuery
解决vue单页使用keep-alive页面返回不刷新的问题
2018/03/13 Javascript
react native 文字轮播的实现示例
2018/07/27 Javascript
解决echarts的多个折现数据出现坐标和值对不上的问题
2018/12/28 Javascript
vue实现扫码功能
2020/01/17 Javascript
[36:05]DOTA2亚洲邀请赛 3.31 小组赛 A组 Liquid vs Optic
2018/04/01 DOTA
Django中使用 Closure Table 储存无限分级数据
2019/06/06 Python
python 正则表达式贪婪模式与非贪婪模式原理、用法实例分析
2019/10/14 Python
利用PyCharm操作Github(仓库新建、更新,代码回滚)
2019/12/18 Python
Python基础之列表常见操作经典实例详解
2020/02/26 Python
Python openpyxl 插入折线图实例
2020/04/17 Python
Python读写压缩文件的方法
2020/07/30 Python
Python常用数字处理基本操作汇总
2020/09/10 Python
python实现邮件循环自动发件功能
2020/09/11 Python
非洲NO.1网上商店:Jumia肯尼亚
2016/08/18 全球购物
美国嘻哈首饰购物网站:Hip Hop Bling
2016/12/30 全球购物
Web Service面试题:如何搭建Axis2的开发环境
2012/06/20 面试题
毕业生护理专业个人求职信范文
2014/01/04 职场文书
奶茶店创业计划书范文
2014/01/17 职场文书
领导班子个人查摆问题对照检查材料
2014/10/02 职场文书
狮子林导游词
2015/02/03 职场文书
三八妇女节新闻稿
2015/07/17 职场文书
中国式结婚:司仪主持词(范文)
2019/07/25 职场文书
Python 数据可视化之Bokeh详解
2021/11/02 Python
Redis keys命令的具体使用
2022/06/05 Redis