exec 语句将 LOAD_GLOBAL 更改为 LOAD_NAME?

2024-04-26

学习中这个答案 https://stackoverflow.com/a/18647337/65696,令我惊讶的是,我发现exec有奇怪的行为;

>>> def f1():
...     return x
... 
>>> def f2():
...     exec ""
...     return x
... 
>>> f1()
Traceback (most recent call last):
  ...
NameError: global name 'x' is not defined
>>> f2()
Traceback (most recent call last):
  ...
NameError: name 'x' is not defined
>>> x = 'bar'
>>> f1()
'bar'
>>> f2()
'bar'

显然,两者都返回一些全局值x;但如果f2()略有改变:

>>> def f2():
...     exec "x = 'im local now'"
...     return x
... 
>>> f2()
'im local now'

f2 返回它自己的特殊副本x,即使 f2 的主体中似乎没有任何内容会导致这种情况(没有分配给 x)。

我可以很容易地看到这是如何发生的,exec声明改变了LOAD_GLOBAL字节码转换为LOAD_NAME,与存在类似yield将函数变成生成器。

>>> dis.dis(f1)
  2           0 LOAD_GLOBAL              0 (x)
              3 RETURN_VALUE        
>>> dis.dis(f2)
  2           0 LOAD_CONST               1 ('')
              3 LOAD_CONST               0 (None)
              6 DUP_TOP             
              7 EXEC_STMT           

  3           8 LOAD_NAME                0 (x)
             11 RETURN_VALUE        

但我不明白的是why。这是有记录的行为吗?这是cpython的实现细节吗? (它在 IronPython 中的工作方式相同,尽管dis模块不起作用)


想象一个更一般的情况:

def f(stuff):
    exec(stuff)
    return x

Python显然必须使用LOAD_NAME这里,因为它不知道代码是否在stuff会搞乱x。同样的情况也适用于any use of exec(),即使参数是一个常量——Python 根本就没有进行足够深入的分析来确定任何exec()碰巧是安全的。

(有一个很好的理由说明为什么它也不应该进行这种分析:唯一的情况是它could即使分析取得任何程度的成功也会exec()不断地争论,这是毫无意义的。如果参数提前完全已知,它应该只是普通代码!)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

exec 语句将 LOAD_GLOBAL 更改为 LOAD_NAME? 的相关文章

随机推荐

  • 跟踪 Maven 中的托管依赖项版本

    假设我有一个复杂的项目 有很多依赖项 依赖项的版本由大量导入范围 pom 管理 我的项目依赖于工件group artifact 它依赖于工件group transitive dependency 当我跑步时dependency tree我看
  • 构造对象并调用成员函数

    这是我的代码 include
  • 如何在 jQuery 移动按钮中使用很棒的字体图标

    我正在尝试使用带有 font Awesome 按钮的 jquery mobile 为此 我遵循了此中描述的答案post https stackoverflow com questions 18809890 how where to inst
  • 在android中加载swf文件时出现问题

    当我在 Android 模拟器中加载交互式 SWF 文件时遇到问题 我使用2 3 1 AVD 这是代码 package com androidpeople view import android app Activity import an
  • '+=' 的含义

    我对 C 的语法感到困惑 有什么用 The 语法可以以不同的方式使用 SomeEvent EventHandler 向事件添加处理程序 SomeVariable 3 相当于 SomeVariable SomeVariable 3
  • Process.Start("explorer.exe");不会带回任务栏

    截至目前 我正在通过 WinForms 开发一个模拟操作系统 以用作电影的道具 运行该应用程序时 它会杀死 explorer exe 这样您就不会在拍摄过程中意外地显示 Windows 任务栏 问题是 关闭模拟操作系统后 我希望 explo
  • 使用我自己的训练示例训练 spaCy 现有的 POS 标记器

    我正在尝试在我自己的词典上训练现有的词性标注器 而不是从头开始 我不想创建一个 空模型 在spaCy的文档中 它说 加载您想要统计的模型 下一步是 使用add label方法将标签映射添加到标记器 但是 当我尝试加载英文小模型并添加标签图时
  • Pandas 获取加载到内存中的所有数据帧的列表

    我正在使用 pandas 将多个 csv 文件读取到内存中进行处理 并且在某些时候想列出我已加载到内存中的所有数据帧 有没有一种简单的方法可以做到这一点 我正在考虑类似 ls 的东西 但仅适用于内存中可用的数据帧 我个人认为this htt
  • 使用一组过滤器在给定区域中最新的 AMI ID

    我正在尝试运行下面的代码 但是在执行时出现错误 您能否建议我进行更改 最新的 ami https github com bwood latest ami blob master latest ami py ec2 user ip XXXXX
  • 尝试通过 ts-patch 在 Angular 项目中使用 ts-nameof

    我正在使用 Angular 8 2 并安装ts nameof https github com dsherret ts nameof ts nameof4 2 2 对于我的项目和ts patch https github com nonar
  • 我如何使用 PyObjects 声明 Boost.Python C++ 类

    我想用 PyObjects 编写一个 C 类 以便从 Python 访问它们 并使用现有的 Python 对象实例引用它们 简而言之 我想在 C 类中存储 管理 Python 对象实例 例如 struct Var PyObject Test
  • 使用 Cerberus 进行依赖项验证

    我正在验证 CSV 文件Cerberus http docs python cerberus org en stable index html但我正在努力解决我认为的一些基本逻辑 设想 CSV 文件有 2 列 Column 2仅当以下情况时
  • 按“字符串”名称对 LINQ 进行排序

    问题解决了 解决方案是 Linq Dynamic 你这样做 from c in Context AccountCharts where c Account FK account c Year FK year select c OrderBy
  • 来自 Phonegap Android 的 AJAX 请求失败

    过去两天我一直在研究这个问题 并查看了很多其他建议 是的 我可以让这个简单的ajax请求在phonegap应用程序中工作 无论是在android模拟器上还是在实际的android手机上 我的phonegap版本是 使用phonegap v
  • 将网站水平和垂直居中

    view on http www eveo org http www eveo org方便修改的下载地址 http www eveo org backup eveo rar http www eveo org backup eveo rar
  • 如何返回 MongoDB 中最新日期的元素

    在 MongoDB 上 如何从此列表中选择具有最新日期的元素 id ObjectId 5c5064f39d0c4b52cf6d1d55 Date 12 09 2018 Type A Value 73650 14 id ObjectId 5c
  • 当 dec 不为 0 时,为什么 0xF00 被解释为 NO

    我发现 BOOL x BOOL 0xF00 is NO 价值0xF00非零 但结果仍然是NO 但这打破了我的范式 BOOL 应该作为 NO 0 YES any other value 为什么会这样呢 这是否意味着检查 if object 不
  • Android volley图片缓存问题

    在google自己的volley图像缓存教程中 Returns a cache size equal to approximately three screens worth of images public static int getC
  • 为什么没有定义 PCTSTR 而定义了 LPCTSTR?

    我被指派更新用 MSVC 6 编写的旧代码 我得到了 PCTSTR 的未知定义 但即使我包含了 tchar h 它也没有定义 根据我以前的经验 我知道有 LPTSTR 但没有 PCTSTR 我 grep C Program Files Mi
  • exec 语句将 LOAD_GLOBAL 更改为 LOAD_NAME?

    学习中这个答案 https stackoverflow com a 18647337 65696 令我惊讶的是 我发现exec有奇怪的行为 gt gt gt def f1 return x gt gt gt def f2 exec retu