Python_Tips[2] -> 函数延后估值及字节码分析
函数延后估值及字节码分析
在一个循环中定义了函数 f 但是并未对其进行调用,在循环结束后调用,此时i值为3故最终3个函数输出均为9。而非1, 4, 9。
这是由于在定义闭包函数 f 时,传入变量 i,而在循环结束后才调用函数,此时的 i 已为 3,下面使用字节码来查看并论证这一运行顺序。
import dis def count():
fs = []
for i in range(1,4):
def f():
return i*i
fs.append(f)
return fs def run():
f1, f2, f3 = count()
# When the function called, the value of i is 3
print(f1())
print(f2())
print(f3()) # dis.dis(count)
run()
使用 dis对count函数的字节码进行查看,得到解释器运行字节码如下
5 0 BUILD_LIST 0
3 STORE_FAST 0 (fs) 6 6 SETUP_LOOP 54 (to 63)
9 LOAD_GLOBAL 0 (range)
12 LOAD_CONST 1 (1)
15 LOAD_CONST 2 (4)
18 CALL_FUNCTION 2 (2 positional, 0 keyword pair)
21 GET_ITER
>> 22 FOR_ITER 37 (to 62)
25 STORE_DEREF 0 (i) 7 28 LOAD_CLOSURE 0 (i)
31 BUILD_TUPLE 1
34 LOAD_CONST 3 (<code object f at 0x0000000000547AE0, file "C:/Users/XXXXX/Documents/Python Note/10_Python_Tips/10.4_Method_Call/Method_Call.py", line 7>)
37 LOAD_CONST 4 ('count.<locals>.f')
40 MAKE_CLOSURE 0
43 STORE_FAST 1 (f) 9 46 LOAD_FAST 0 (fs)
49 LOAD_ATTR 1 (append)
52 LOAD_FAST 1 (f)
55 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
58 POP_TOP
59 JUMP_ABSOLUTE 22
>> 62 POP_BLOCK 10 >> 63 LOAD_FAST 0 (fs)
66 RETURN_VALUE
通过字节码可以看到,
第 10 行进入迭代,
第 11 行中的 STORE_DEREF 会更新变量 i 的值,
第 13 行开始,进入到函数 f 定义的部分,而第 13 行则是关键,这里载入 Enclosure 即闭包上层的局部变量 i,而不是当前 i 的值,随后完成整个闭包函数 f 并返回。
因此,在 3 个函数 f 中,所存储的均为变量 i,所以在调用时结果自然相同。
相关阅读
1. 闭包函数
Python_Tips[2] -> 函数延后估值及字节码分析的更多相关文章
- Java并发编程原理与实战八:产生线程安全性问题原因(javap字节码分析)
前面我们说到多线程带来的风险,其中一个很重要的就是安全性,因为其重要性因此,放到本章来进行讲解,那么线程安全性问题产生的原因,我们这节将从底层字节码来进行分析. 一.问题引出 先看一段代码 packa ...
- 通过字节码分析this关键字以及异常表的重要作用
在之前的字节码分析中缺少对异常的介绍,这次主要来对字节码异常表相关的东东进行一个学习,下面先来编写一个相关异常的小程序: 接着编译来看用javap -verbose来查看一下它的字节码信息: xion ...
- JVM-String比较-字节码分析
一道String字符串比较问题引发的字节码分析 public class a { public static void main(String[] args)throws Exception{ } p ...
- Java字节码分析
目录 Java字节码分析 查看字节码详细内容 javap 实例分析 Java字节码分析 对于源码的效率,但从源码来看有时无法分析出准确的结果,因为不同的编译器版本可能会将相同的源码编译成不同的字节码, ...
- 通过字节码分析java中的switch语句
在一次做题中遇到了switch的问题,由于对switch执行顺序的不了解,在这里简单的通过字节码的方式理解一下switch执行顺序(题目如下): public class Ag{ static pub ...
- Java Eclipse编译后产生的字节码文件,用DOS命令符怎么打开
在很多初学者刚刚接触eclipse的时候,写完一个代码文件.例如 Demo.java 通过run as a java application生成之后,会产生一个Demo.class. Demo.cla ...
- 深挖JDK动态代理(二):JDK动态生成后的字节码分析
接上一篇文章深挖JDK动态代理(一)我们来分析一下JDK生成动态的代理类究竟是个什么东西 1. 将生成的代理类编程一个class文件,通过以下方法 public static void transCl ...
- java中i=i++字节码分析
原文出处: Ticmy 1 2 int i = 0; i = i++; 结果还是0为什么? 程序的执行顺序是这样的:因为++在后面,所以先使用i,"使用"的含义就是i++这个表达式 ...
- Java finally语句到底是在return之前还是之后执行(JVM字节码分析及内部体系结构)?
之前看了一篇关于"Java finally语句到底是在return之前还是之后执行?"这样的博客,看到兴致处,突然博客里的一个测试用例让我产生了疑惑. 测试用例如下: public ...
随机推荐
- 《Cracking the Coding Interview》——第1章:数组和字符串——题目2
2014-03-18 01:30 题目:反转一个char *型的C/C++字符串. 解法:一头一尾俩iterator,向中间靠拢并且交换字符. 代码: // 1.2 Implement a funct ...
- Python import与from import使用
Python程序可以调用一组基本的函数(即内建函数),比如print().input()和len()等函数.Python本身也内置一组模块(即标准库).每个模块都是一个Python程序,且包含了一组相 ...
- NGUI执行基本事件的原理
通常我们为对象附加一个脚本组件,脚本组件只要加此鼠标处理事件方法,这个对象就有了点击事件了: void OnClick() { Debug.Log("onclick"); } 可为 ...
- Python网络编程(epoll内核监听,多任务多进程)
OJBK 接着昨天的说 select模块内的epoll函数还没说 说完epoll和本地套接字套接字基本就没了 今天主要是多进程 理论性东西比较多 主要是理解 epoll ...
- Opencv4.0.0安装包
这个资源是Opencv4.0.0安装包,包括Windows软件包,Android软件包,IOS软件包,还有opencv的源代码:需要的下载吧. 点击下载
- Ext中关于Ext.QuickTips.init()的使用
在extJS的例子中,大部分都在程序第一行使用了如下语句:Ext.QuickTips.init();但是QuickTips的用处是什么呢?我们看一段最简单的代码: <html> <h ...
- 实验 使用 vivado zedboard GPIO 开关 开控制 LED
前面我做了几个实验 都没有用过 开关,这一次用一用 发现 vivado 真的挺方便 所以 使用 vivado 开发 1.建工程 我使用 vivado 2013.4 创建新工程 –> next – ...
- Java 实现二叉树的构建以及3种遍历方法
转载自http://ocaicai.iteye.com/blog/1047397 大二下学期学习数据结构的时候用C介绍过二叉树,但是当时热衷于java就没有怎么鸟二叉树,但是对二叉树的构建及遍历一直耿 ...
- file mmap
do_set_pmd 统计参数只会在这里设置: add_mm_counter(vma->vm_mm, MM_FILEPAGES, HPAGE_PMD_NR); 但是这貌似都是处理大页的情况哪,小 ...
- [CF1000E]We Need More Bosses
题目大意:给一张无向图,要求找一对$s$和$t$,使得其路径上的割边是最多的,输出其数量. 题解:把边双缩点以后求树的直径. 卡点:无 C++ Code: #include <cstdio> ...