使用 exec 调用时如何更新局部变量?

新手上路,请多包涵

我以为这会打印 3,但它打印了 1:

 # Python3

def f():
    a = 1
    exec("a = 3")
    print(a)

f()
# 1 Expected 3

原文由 ubershmekel 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

这个问题在 Python3 错误列表 中有所讨论。最终,要获得此行为,您需要执行以下操作:

 def foo():
    ldict = {}
    exec("a=3",globals(),ldict)
    a = ldict['a']
    print(a)

如果您查看 exec 上的 Python3 文档,您将看到以下注释:

默认局部变量的行为如下面的函数 locals() 所述: 不应尝试修改默认局部变量字典。如果您需要在函数 exec() 返回后查看代码对局部变量的影响,请传递一个显式局部变量字典。

这意味着单参数 exec 不能安全地执行任何绑定局部变量的操作,包括变量赋值、导入、函数定义、类定义等。如果它使用 global 它可以分配给全局变量 --- 声明,但不是本地人。

Georg Brandl 回顾 错误报告中的特定消息 说:

动态修改函数的局部变量不可能没有几个后果: 通常,函数局部变量不存储在字典中,而是存储在数组 中,其索引是在编译时根据已知语言环境确定的。这至少与 exec 添加的新本地人发生冲突。旧的 exec 语句规避了这一点,因为编译器知道如果函数中出现没有全局/局部参数的 exec,则该命名空间将是“未优化的”,即不使用局部数组。由于 exec() 现在是一个普通函数, 编译器不知道“exec”可能绑定到什么,因此不能特别对待 is

重点是我的。

所以它的要点是Python3可以通过默认 不允许 这种行为来更好地优化局部变量的使用。

为了完整起见,如上面评论中所述,这在 Python 2.X 中 确实 按预期工作:

 Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41)
[GCC 4.3.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> def f():
...     a = 1
...     exec "a=3"
...     print a
...
>>> f()
3

原文由 Mark Rushakoff 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题