函数延后估值及字节码分析


在一个循环中定义了函数 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] -> 函数延后估值及字节码分析的更多相关文章

  1. Java并发编程原理与实战八:产生线程安全性问题原因(javap字节码分析)

    前面我们说到多线程带来的风险,其中一个很重要的就是安全性,因为其重要性因此,放到本章来进行讲解,那么线程安全性问题产生的原因,我们这节将从底层字节码来进行分析. 一.问题引出 先看一段代码 packa ...

  2. 通过字节码分析this关键字以及异常表的重要作用

    在之前的字节码分析中缺少对异常的介绍,这次主要来对字节码异常表相关的东东进行一个学习,下面先来编写一个相关异常的小程序: 接着编译来看用javap -verbose来查看一下它的字节码信息: xion ...

  3. JVM-String比较-字节码分析

    一道String字符串比较问题引发的字节码分析 public class a { public static void main(String[] args)throws Exception{ } p ...

  4. Java字节码分析

    目录 Java字节码分析 查看字节码详细内容 javap 实例分析 Java字节码分析 对于源码的效率,但从源码来看有时无法分析出准确的结果,因为不同的编译器版本可能会将相同的源码编译成不同的字节码, ...

  5. 通过字节码分析java中的switch语句

    在一次做题中遇到了switch的问题,由于对switch执行顺序的不了解,在这里简单的通过字节码的方式理解一下switch执行顺序(题目如下): public class Ag{ static pub ...

  6. Java Eclipse编译后产生的字节码文件,用DOS命令符怎么打开

    在很多初学者刚刚接触eclipse的时候,写完一个代码文件.例如 Demo.java 通过run as a java application生成之后,会产生一个Demo.class. Demo.cla ...

  7. 深挖JDK动态代理(二):JDK动态生成后的字节码分析

    接上一篇文章深挖JDK动态代理(一)我们来分析一下JDK生成动态的代理类究竟是个什么东西 1. 将生成的代理类编程一个class文件,通过以下方法 public static void transCl ...

  8. java中i=i++字节码分析

    原文出处: Ticmy 1 2 int i = 0; i = i++; 结果还是0为什么? 程序的执行顺序是这样的:因为++在后面,所以先使用i,"使用"的含义就是i++这个表达式 ...

  9. Java finally语句到底是在return之前还是之后执行(JVM字节码分析及内部体系结构)?

    之前看了一篇关于"Java finally语句到底是在return之前还是之后执行?"这样的博客,看到兴致处,突然博客里的一个测试用例让我产生了疑惑. 测试用例如下: public ...

随机推荐

  1. 阿里云ECS Ubuntu安装PHP+Mysql+Apache+Nginx+Redis+Discuz

    http://www.linuxdiyf.com/linux/13662.html http://blog.csdn.net/wangnan537/article/details/47868659 h ...

  2. python - web自动化测试 - 元素操作 - 鼠标键盘

    # -*- coding:utf-8 -*- ''' @project: web学习 @author: Jimmy @file: 鼠标操作.py @ide: PyCharm Community Edi ...

  3. GLIBCXX3.4.21 not find

    在执行世界杯的二进制代码和安装keepaway中会遇到GLIBCXX3.4.21 not find的问题,其解决办法就是升级安装GCC. 一.首先查看当前gcc版本 $ strings /usr/li ...

  4. win10 ubuntu16双系统安装教程

    一. 知识准备 1.材料 前提: 本文档是在win10 64位下进行安装的!32位的安装注意其中的一些细节即可 硬件: X86_64 位电脑 硬盘有 40G 空闲 软件:[百度搜索即可] (1) Ul ...

  5. linux误删除恢复

    extundelete 大家基本都知道,在linux上误删除了东西后果是很严重的,尤其是在服务器上误删除了东西,对于字符终端,想要实现恢复删除的数据更是难上加难,对于Linux误删除了重要的东西,虽然 ...

  6. nyoj 题目49 开心的小明

    开心的小明 时间限制:1000 ms  |  内存限制:65535 KB 难度:4   描述 小明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天 ...

  7. 关于usr/bin/ld: cannot find -lxxx问题总结(Qt编译错误cannot find -lGL)

    决定终结这个问题!(网上要想找到完整的解答实在太难了) http://blog.sciencenet.cn/blog-676535-541444.html 前两天手贱,把虚拟机玩崩溃了,只好重装虚拟机 ...

  8. Scala 基础(5)—— 构建函数式对象

    有了 Scala 基础(4)—— 类和对象 的前提,现在就可以来构建一个基于 Scala 的函数式对象. 下面开始构造一个有理数对象 Rational. 1. 主构造方法和辅助构造方法 对于每一个类的 ...

  9. P4160 [SCOI2009]生日快乐

    题目描述 windy的生日到了,为了庆祝生日,他的朋友们帮他买了一个边长分别为 X 和 Y 的矩形蛋糕. 现在包括windy,一共有 N 个人来分这块大蛋糕,要求每个人必须获得相同面积的蛋糕. win ...

  10. Codeforces Round #336 (Div. 2) A

    A. Saitama Destroys Hotel time limit per test 1 second memory limit per test 256 megabytes input sta ...