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优先队列实现方法示例
Sep 21 Python
Python判断两个list是否是父子集关系的实例
May 04 Python
详解Python if-elif-else知识点
Jun 11 Python
python操作excel文件并输出txt文件的实例
Jul 10 Python
Python 一键制作微信好友图片墙的方法
May 16 Python
python爬虫项目设置一个中断重连的程序的实现
Jul 26 Python
Python中变量的输入输出实例代码详解
Jul 28 Python
Python3 文章标题关键字提取的例子
Aug 26 Python
tensorflow实现训练变量checkpoint的保存与读取
Feb 10 Python
python中类与对象之间的关系详解
Dec 16 Python
Python爬虫制作翻译程序的示例代码
Feb 22 Python
利用Python判断你的密码难度等级
Jun 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上传图片生成缩略图(GD库)
2016/01/06 PHP
php版微信开发之接收消息,自动判断及回复相应消息的方法
2016/09/23 PHP
thinkPHP显示不出验证码的原因与解决方法分析
2017/05/20 PHP
javascript new fun的执行过程
2010/08/05 Javascript
ListBox实现上移,下移,左移,右移的简单实例
2014/02/13 Javascript
jQuery中get和post方法传值测试及注意事项
2014/08/08 Javascript
JQuery表单验证插件EasyValidator用法分析
2014/11/15 Javascript
AngularJS ng-bind 指令简单实现
2016/07/30 Javascript
超详细的JS弹出窗口代码大全
2020/04/18 Javascript
node.js路径处理方法以及绝对路径详解
2021/03/04 Javascript
JQueryEasyUI之DataGrid数据显示
2016/11/23 Javascript
javascript 显示全局变量与隐式全局变量的区别
2017/02/09 Javascript
JQuery validate 验证一个单独的表单元素实例
2017/02/17 Javascript
深入理解Vue-cli搭建项目后的目录结构探秘
2017/07/13 Javascript
详解JS中的this、apply、call、bind(经典面试题)
2017/09/19 Javascript
vue axios 给生产环境和发布环境配置不同的接口地址(推荐)
2018/05/08 Javascript
validform表单验证的实现方法
2019/03/08 Javascript
深入理解Antd-Select组件的用法
2020/02/25 Javascript
JavaScript数组排序的六种常见算法总结
2020/08/18 Javascript
对Python的Django框架中的项目进行单元测试的方法
2016/04/11 Python
对TensorFlow的assign赋值用法详解
2018/07/30 Python
Python3爬虫之自动查询天气并实现语音播报
2019/02/21 Python
基于python3 的百度图片下载器的实现代码
2019/11/05 Python
python 实现多线程下载m3u8格式视频并使用fmmpeg合并
2019/11/15 Python
实现Python与STM32通信方式
2019/12/18 Python
tensorflow中tf.slice和tf.gather切片函数的使用
2020/01/19 Python
Python实现Keras搭建神经网络训练分类模型教程
2020/06/12 Python
Python Opencv图像处理基本操作代码详解
2020/08/31 Python
Anaconda详细安装步骤图文教程
2020/11/12 Python
Kivari官网:在线购买波西米亚服装
2018/10/29 全球购物
澳大利亚在线消费电子产品商店:TobyDeals
2020/01/05 全球购物
标记环网Toke Ring IEEE802.5
2014/05/26 面试题
琅琊山导游词
2015/02/05 职场文书
SQL SERVER存储过程用法详解
2022/02/24 SQL Server
mysql 生成连续日期及变量赋值
2022/03/20 MySQL
关于python3 opencv 图像二值化的问题(cv2.adaptiveThreshold函数)
2022/04/04 Python