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数据结构之Array用法实例
Oct 09 Python
在Python程序中操作文件之isatty()方法的使用教程
May 24 Python
python 获取字符串MD5值方法
May 29 Python
Sanic框架流式传输操作示例
Jul 18 Python
对python中矩阵相加函数sum()的使用详解
Jan 28 Python
Python基础学习之函数方法实例详解
Jun 18 Python
Django 开发环境配置过程详解
Jul 18 Python
pycharm设置python文件模板信息过程图解
Mar 10 Python
解决jupyter notebook 前面书写后面内容消失的问题
Apr 13 Python
使用Pycharm(Python工具)新建项目及创建Python文件的教程
Apr 26 Python
Python使用pyenv实现多环境管理
Feb 05 Python
Python利用folium实现地图可视化
May 23 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采集相关教程之一 CURL函数库
2010/02/15 PHP
php下保存远程图片到本地的办法
2010/08/08 PHP
php实现最简单的MVC框架实例教程
2014/09/08 PHP
PHP实现通过正则表达式替换回调的内容标签
2015/06/15 PHP
apache php mysql开发环境安装教程
2016/07/28 PHP
JavaScript小技巧 2.5 则
2010/09/12 Javascript
封装了一个支持匿名函数的Javascript事件监听器
2014/06/05 Javascript
超链接的禁用属性Disabled使用示例
2014/07/31 Javascript
使用script的src实现跨域和类似ajax效果
2014/11/10 Javascript
webpack学习--webpack经典7分钟入门教程
2017/06/28 Javascript
backbone简介_动力节点Java学院整理
2017/07/14 Javascript
JS非空验证及邮箱验证的实例
2017/08/11 Javascript
关于JS模块化的知识点分享
2019/10/16 Javascript
Javascript摸拟自由落体与上抛运动原理与实现方法详解
2020/04/08 Javascript
简单的Apache+FastCGI+Django配置指南
2015/07/22 Python
socket + select 完成伪并发操作的实例
2017/08/15 Python
Python工厂函数用法实例分析
2018/05/14 Python
Pyqt5 基本界面组件之inputDialog的使用
2019/06/25 Python
基于Python的图像数据增强Data Augmentation解析
2019/08/13 Python
Python命令行click参数用法解析
2019/12/19 Python
Python二元算术运算常用方法解析
2020/09/15 Python
Pycharm在指定目录下生成文件和删除文件的实现
2020/12/28 Python
css3一款3D字体带阴影效果的实现步骤
2013/03/20 HTML / CSS
台湾乐天市场:日本No.1的网路购物网站
2017/03/22 全球购物
北美领先的智能产品购物网站:Wellbots
2018/06/11 全球购物
美国潜水装备、水肺潜水和浮潜设备商店:Leisure Pro
2018/08/08 全球购物
英国现代家具和照明购物网站:Heal’s
2019/10/30 全球购物
德尔福集团DELPHI的笔试题
2012/02/22 面试题
企业军训感言
2014/02/08 职场文书
开学典礼感言
2014/02/16 职场文书
事业单位鉴定材料
2014/05/25 职场文书
协会周年庆活动方案
2014/08/26 职场文书
地方白酒代理协议书
2014/10/25 职场文书
考试没考好检讨书
2015/05/06 职场文书
学校2016年全国助残日活动总结
2016/04/01 职场文书
利用 SQL Server 过滤索引提高查询语句的性能分析
2021/07/15 SQL Server