对python的LOAD_FAST/STORE_FAST感到困惑

2024-03-04

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

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

test()

import dis
dis.dis(test)

输出是:

<function test.<locals>.f at 0x7f46c0b0d400>
<function test.<locals>.f at 0x7f46c0b0d488>
<function test.<locals>.f at 0x7f46c0b0d400>
<function test.<locals>.f at 0x7f46c0b0d488>
<function test.<locals>.f at 0x7f46c0b0d400>
<function test.<locals>.f at 0x7f46c0b0d488>
<function test.<locals>.f at 0x7f46c0b0d400>
<function test.<locals>.f at 0x7f46c0b0d488>
<function test.<locals>.f at 0x7f46c0b0d400>
<function test.<locals>.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 (<code object f at 0x7f46c0bd8420, file "ts.py", line 8>)
             28 LOAD_CONST               3 ('test.<locals>.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

when

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

test()

import dis
dis.dis(test)

输出是:

<function test.<locals>.f at 0x7ff88ffe0400>
<function test.<locals>.f at 0x7ff88ffe0488>
<function test.<locals>.f at 0x7ff88ffe0510>
<function test.<locals>.f at 0x7ff88ffe0598>
<function test.<locals>.f at 0x7ff88ffe0620>
<function test.<locals>.f at 0x7ff88ffe06a8>
<function test.<locals>.f at 0x7ff88ffe0730>
<function test.<locals>.f at 0x7ff88ffe07b8>
<function test.<locals>.f at 0x7ff88ffe0840>
<function test.<locals>.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 (<code object f at 0x7ff8900ab420, file "ts.py", line 8>)
             28 LOAD_CONST               3 ('test.<locals>.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

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

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

难道LOAD_FAST/STORE FAST做了一些未知的事情?


发生这种情况是因为在每次交替迭代中,在重新声明当前函数对象之后,旧函数对象会被重新声明。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()
<function f at 0x00007f055c77d5b0>
<function f at 0x00007f055c77d628>
<function f at 0x00007f055c77d6a0>
<function f at 0x00007f055c77d718>
<function f at 0x00007f055c77d790>
<function f at 0x00007f055c77d808>
<function f at 0x00007f055c77d880>
<function f at 0x00007f055c77d8f8>
<function f at 0x00007f055c77d970>
<function f at 0x00007f055c77d9e8>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对python的LOAD_FAST/STORE_FAST感到困惑 的相关文章

随机推荐

  • python 中的对象初始值设定项语法(c#)?

    我想知道是否有一种快速的方法来初始化Python中的对象 例如 在 c 中 您可以实例化一个对象并设置字段 属性 例如 SomeClass myObject new SomeClass variableX value variableY 1
  • 从 ASP.NET MVC Lambda 表达式获取价值

    我正在尝试创建自己的 HTML 帮助器 它接受一个表达式 类似于内置的 LabelFor 帮助器 我找到了当表达式与此类似时获取属性值的示例 model gt model Forename 但是 在我的一些模型中 我想获取子元素中的属性 例
  • Python 电子邮件 PDF:某些 PDF 已损坏

    我正在尝试将 PDF 文件附加到电子邮件中 对于一个 PDF 打印为 PDF 的 Word 文档 它可以工作 收件人在 Outlook 中打开它没有问题 然而 对于其他 PDF 除了大了几 KB 之外 它们看起来都一样 它们会被损坏 是一个
  • Android - 解决 ACCESS_CONTENT_PROVIDERS_EXTERNALLY 权限?

    我正在构建一个应用程序 它给出了这个异常 因为我调用了一些内部方法 权限拒绝 没有从 pid 2520 uid 10047 调用 getContentProviderExternal 的权限 需要 android permission AC
  • WTSEnumerateSessions 挂起并且永不返回

    我有一个用 C 编写的 Net 服务 我正在调用WTSEnumerateSessions 会话检查由计时器每 15 分钟运行一次 它列出所有会话并将用户名 域组合与预定义的用户集进行比较 以确定他们是否登录到服务器 问题在于几个服务器的调用
  • C# 程序运行时初始形式不可用

    我在让程序中的主窗体按我想要的方式运行时遇到问题 我正在使用 C 在我的初始主窗体 Form1 上 我有一个运行长程序的命令按钮 在程序中间 我希望用户能够返回到初始表单并单击一些新的复选框 我将从 C 程序中将其放置在该初始表单上 下面的
  • Telegram 中的“Simple PUSH”事件如何运作?

    The 用于订阅 Telegram API 中的 PUSH 基础设施的文档 https core telegram org method account registerDevice非常缺乏 因为主要是专注于移动平台 https core
  • Cakephp - 如何使错误页面有自己的布局?

    我想要为未找到 404 页面使用不同的布局 我如何为该页面设置不同的布局 IRC 的专家帮助了我 他建议使用beforeRender 在应用程序控制器中 Before Render function beforeRender if this
  • 未将 Win32 可移植可执行映像映射到偏移量 0 处的可能原因有哪些?

    我最近一直在研究 Window 的 PE 格式 我注意到在大多数示例中 人们倾向于设定ImageBase中的偏移值optional header到一些不合理的高的东西 比如0x400000 什么可能使它不利not在偏移处映射图像0x0 首先
  • Files.walkFileTree中的遍历顺序

    顺序是什么Files walkFileTree访问同一级别的文件 目录 它似乎没有按大小 上次修改时间或名称的顺序访问它们 我在其中找不到任何内容API文档 http docs oracle com javase 7 docs api ja
  • 如何在 MiniTest 中存根?

    在我的测试中 我想为类的任何实例存根一个预设的响应 它可能看起来像这样 Book stubs title any instance returns War and Peace 然后每当我打电话时 book title它返回 战争与和平 有没
  • 如何更新TileOverlay而不闪烁?

    我有一些动态图块内容要显示在地图顶部 具体来说 天气图像 雷达 卫星 温度等 我正在使用适用于 Android v2 的 Google 地图 API 我遇到的问题是 显然更新图块图像的唯一方法 即当新数据到达时 或者当帧在延时动画中前进时
  • 使用 LoadLibrary 在 .pyd 中加载 cython cdef 函数时出现问题

    我正在尝试在 C 中动态加载 cythonized pyd 在 Linux 机器中创建一个 so 文件 使用 so 我可以执行以下操作 plugin dlopen foo so RTLD LAZY init dlsym plugin PyI
  • 调试 Jersey 解组错误 - 错误请求语法不正确

    我正在 Glassfish 上的 Jersey 的帮助下构建 REST Web 服务 现在我正在为我的搜索查询的自定义输入源而苦苦挣扎 如果有搜索方法 POST Path search Consumes application xml ap
  • HSTS 预加载列表 - www 网站可能存在 SEO 问题

    让我在这里解释一下现实世界的情况 我运行网站https www liloo ro https www liloo ro我想为其启用 HSTS HSTS 预加载 问题是为了将其提交给预加载列表 https hstspreload org th
  • 无法制作固定大小数组的向量?

    我有这个奇怪的问题 vector
  • 更改 igraph 图中子图的颜色

    我有以下代码来绘制图的最小生成树 g is an igraph graph mst minimum spanning tree g E g color lt SkyBlue2 how to I make mst a different co
  • 无法访问用户控制组件[关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 在我的用户控件中 我有一个名为的 datagridviewdgvCustomers 我想在 gridview 中加载客户
  • 延长 R 中绘图轴的长度?

    如何在 R 中扩展轴线以覆盖数据范围 例如 在 我的数据大约为 2100 我希望 x 轴的线能走那么远 但不要在 2100 处做刻度线或标签 这在 R 中是否可能 这是用于制作上述绘图的代码 hist x breaks 50 xlab ma
  • 对python的LOAD_FAST/STORE_FAST感到困惑

    当我写一些代码时 我发现一个有趣的事情 def test l for i in range 10 def f pass print f l append f test import dis dis dis test 输出是