以下代码在 Python2
和 Python3
中给出了不同的输出:
from sys import version
print(version)
def execute(a, st):
b = 42
exec("b = {}\nprint('b:', b)".format(st))
print(b)
a = 1.
execute(a, "1.E6*a")
Python2
打印:
2.7.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit (Intel)]
('b:', 1000000.0)
1000000.0
Python3
打印:
3.2.3 (default, Apr 11 2012, 07:15:24) [MSC v.1500 32 bit (Intel)]
b: 1000000.0
42
为什么 Python2
将 execute
函数中的变量 b
绑定(bind)到 exec
的字符串中的值> 函数,而 Python3
不这样做?如何在 Python3
中实现 Python2
的行为?我已经尝试将全局变量和局部变量的字典传递给 Python3
中的 exec
函数,但到目前为止没有任何效果。
--- 编辑 ---
阅读 Martijns 的回答后,我用 Python3
进一步分析了这个问题。在下面的示例中,我将 locals()
字典作为 d
给 exec
,但是 d['b']
打印的不仅仅是打印 b
。
from sys import version
print(version)
def execute(a, st):
b = 42
d = locals()
exec("b = {}\nprint('b:', b)".format(st), globals(), d)
print(b) # This prints 42
print(d['b']) # This prints 1000000.0
print(id(d) == id(locals())) # This prints True
a = 1.
execute(a, "1.E6*a")
3.2.3 (default, Apr 11 2012, 07:15:24) [MSC v.1500 32 bit (Intel)]
b: 1000000.0
42
1000000.0
True
比较d
和locals()
的id,发现是同一个对象。但在这些条件下,b
应该与 d['b']
相同。我的示例有什么问题?
最佳答案
Python 2 中的 exec
和 Python 3 中的 exec()
有很大区别。你把 exec
当作一个函数,但它确实是 Python 2 中的一个语句。
由于这种差异,您不能在 Python 3 中使用 exec
更改函数范围内的局部变量,即使在 Python 2 中是可能的。甚至以前声明的变量也不行。
locals()
只反射(reflect)一个方向的局部变量。以下内容在 2 或 3 中都不起作用:
def foo():
a = 'spam'
locals()['a'] = 'ham'
print(a) # prints 'spam'
在 Python 2 中,使用 exec
语句意味着编译器知道关闭局部作用域优化(从 LOAD_FAST
切换到 LOAD_NAME
例如,在局部和全局范围内查找变量)。由于 exec()
是一个函数,该选项不再可用并且函数作用域现在总是优化。
此外,在 Python 2 中,exec
语句使用 PyFrame_LocalsToFast
显式地将在 locals()
中找到的所有变量复制回函数 locals,但前提是没有提供globals 和locals 参数。
正确的解决方法是为您的 exec()
调用使用新的命名空间(字典):
def execute(a, st):
namespace = {}
exec("b = {}\nprint('b:', b)".format(st), namespace)
print(namespace['b'])
exec()
documentation对这个限制非常明确:
Note: The default locals act as described for function
locals()
below: modifications to the default locals dictionary should not be attempted. Pass an explicit locals dictionary if you need to see effects of the code on locals after functionexec()
returns.
关于python - Python 2 和 Python 3 中 exec 函数的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40638179/