热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

困惑于python的LOAD_FAST/STORE_FAST

如何解决《困惑于python的LOAD_FAST/STORE_FAST》经验,为你挑选了1个好方法。

当我写一些代码时,我发现了一件有趣的事情:

def test():
  l = []
  for i in range(10):
    def f():pass
    print(f)
    #l.append(f)

test()

import dis
dis.dis(test)

输出是:

.f at 0x7f46c0b0d400>
.f at 0x7f46c0b0d488>
.f at 0x7f46c0b0d400>
.f at 0x7f46c0b0d488>
.f at 0x7f46c0b0d400>
.f at 0x7f46c0b0d488>
.f at 0x7f46c0b0d400>
.f at 0x7f46c0b0d488>
.f at 0x7f46c0b0d400>
.f at 0x7f46c0b0d488>
  6           0 BUILD_LIST               0
              3 STORE_FAST               0 (l)

  7           6 SETUP_LOOP              42 (to 51)
              9 LOAD_GLOBAL              0 (range)
             12 LOAD_CONST               1 (10)
             15 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             18 GET_ITER
        >>   19 FOR_ITER                28 (to 50)
             22 STORE_FAST               1 (i)

  8          25 LOAD_CONST               2 ()
             28 LOAD_CONST               3 ('test..f')
             31 MAKE_FUNCTION            0
             34 STORE_FAST               2 (f)

  9          37 LOAD_GLOBAL              1 (print)
             40 LOAD_FAST                2 (f)
             43 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             46 POP_TOP
             47 JUMP_ABSOLUTE           19
        >>   50 POP_BLOCK
        >>   51 LOAD_CONST               0 (None)
             54 RETURN_VALUE

什么时候

def test():
  l = []
  for i in range(10):
    def f():pass
    print(f)
    l.append(f)

test()

import dis
dis.dis(test)

输出是:

.f at 0x7ff88ffe0400>
.f at 0x7ff88ffe0488>
.f at 0x7ff88ffe0510>
.f at 0x7ff88ffe0598>
.f at 0x7ff88ffe0620>
.f at 0x7ff88ffe06a8>
.f at 0x7ff88ffe0730>
.f at 0x7ff88ffe07b8>
.f at 0x7ff88ffe0840>
.f at 0x7ff88ffe08c8>
  6           0 BUILD_LIST               0
              3 STORE_FAST               0 (l)

  7           6 SETUP_LOOP              55 (to 64)
              9 LOAD_GLOBAL              0 (range)
             12 LOAD_CONST               1 (10)
             15 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             18 GET_ITER
        >>   19 FOR_ITER                41 (to 63)
             22 STORE_FAST               1 (i)

  8          25 LOAD_CONST               2 ()
             28 LOAD_CONST               3 ('test..f')
             31 MAKE_FUNCTION            0
             34 STORE_FAST               2 (f)

  9          37 LOAD_GLOBAL              1 (print)
             40 LOAD_FAST                2 (f)
             43 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             46 POP_TOP

 10          47 LOAD_FAST                0 (l)
             50 LOAD_ATTR                2 (append)
             53 LOAD_FAST                2 (f)
             56 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             59 POP_TOP
             60 JUMP_ABSOLUTE           19
        >>   63 POP_BLOCK
        >>   64 LOAD_CONST               0 (None)
             67 RETURN_VALUE

如果STORE_FAST"缓存"了f,为什么在第一个代码片段中,地址f是交替的?

在第二个片段中,它有两个LOAD_FAST,结果是正常的.

LOAD_FAST/STORE_FAST做了一些不知情的事吗?



1> Ashwini Chau..:

这种情况正在发生,因为在每次交替迭代中,重新声明当前的旧函数对象f没有引用,因此它被垃圾收集,Python可以在下一次迭代中重用该内存空间.另一方面,在第二个列表中,列表指的是每个函数,因此它们永远不会被垃圾回收.

这是一个依赖于实现的东西,CPython的垃圾收集基于引用计数.在PyPy上,输出是不同的:

$ ~/pypy-2.4.0-linux64/bin# ./pypy 
Python 2.7.8 (f5dcc2477b97, Sep 18 2014, 11:33:30)
[PyPy 2.4.0 with GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>> def test():
....     for i in range(10):
....         def f(): pass
....         print f
.... 
>>>> test()











推荐阅读
  • 1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ... [详细]
  • 本文探讨了如何在给定整数N的情况下,找到两个不同的整数a和b,使得它们的和最大,并且满足特定的数学条件。 ... [详细]
  • CentOS7源码编译安装MySQL5.6
    2019独角兽企业重金招聘Python工程师标准一、先在cmake官网下个最新的cmake源码包cmake官网:https:www.cmake.org如此时最新 ... [详细]
  • 前言--页数多了以后需要指定到某一页(只做了功能,样式没有细调)html ... [详细]
  • 本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ... [详细]
  • 在Ubuntu 16.04 LTS上配置Qt Creator开发环境
    本文详细介绍了如何在Ubuntu 16.04 LTS系统中安装和配置Qt Creator,涵盖了从下载到安装的全过程,并提供了常见问题的解决方案。 ... [详细]
  • 本文详细解析了Python中的os和sys模块,介绍了它们的功能、常用方法及其在实际编程中的应用。 ... [详细]
  • 尽管使用TensorFlow和PyTorch等成熟框架可以显著降低实现递归神经网络(RNN)的门槛,但对于初学者来说,理解其底层原理至关重要。本文将引导您使用NumPy从头构建一个用于自然语言处理(NLP)的RNN模型。 ... [详细]
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
  • 深入解析Spring Cloud Ribbon负载均衡机制
    本文详细介绍了Spring Cloud中的Ribbon组件如何实现服务调用的负载均衡。通过分析其工作原理、源码结构及配置方式,帮助读者理解Ribbon在分布式系统中的重要作用。 ... [详细]
  • C++: 实现基于类的四面体体积计算
    本文介绍如何使用C++编程语言,通过定义类和方法来计算由四个三维坐标点构成的四面体体积。文中详细解释了四面体体积的数学公式,并提供了两种不同的实现方式。 ... [详细]
  • 本章将深入探讨移动 UI 设计的核心原则,帮助开发者构建简洁、高效且用户友好的界面。通过学习设计规则和用户体验优化技巧,您将能够创建出既美观又实用的移动应用。 ... [详细]
  • 在 Swift 编程中,遇到错误提示“一元运算符 '!' 不能应用于 '()' 类型的操作数”,通常是因为尝试对没有返回值的方法或函数应用逻辑非运算符。本文将详细解释该错误的原因,并提供解决方案。 ... [详细]
  • 本文由瀚高PG实验室撰写,详细介绍了如何在PostgreSQL中创建、管理和删除模式。文章涵盖了创建模式的基本命令、public模式的特性、权限设置以及通过角色对象简化操作的方法。 ... [详细]
  • 获取计算机硬盘序列号的方法与实现
    本文介绍了如何通过编程方法获取计算机硬盘的唯一标识符(序列号),并提供了详细的代码示例和解释。此外,还涵盖了如何使用这些信息进行身份验证或注册保护。 ... [详细]
author-avatar
天涯小犁_640
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有