以下代码在Python2和 中给出不同的输出Python3:
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变量绑定到函数字符串中的值,而 while却不这样做?如何实现in的行为?我已经尝试将全局和局部的字典传递给in 函数,但到目前为止没有任何效果。b``execute``exec``Python3``Python2``Python3``exec``Python3
b``execute``exec``Python3``Python2``Python3``exec``Python3
- - 编辑 - -
在阅读了 Martijns 的回答后,我进一步分析了这一点Python3。在下面的例子中,我给出了字典locals(),但打印的内容不仅仅是打印。d``exec``d['b']``b
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和的 id 比较locals()表明它们是同一个对象。但在这种情况下b应该与 相同d['b']。我的示例中有什么问题?
d
b
d['b']
execPython 2 和Python 3之间存在很大差异。exec()您将其视为exec一个函数,但在 Python 2 中它实际上是一个语句。
exec
exec()
由于这个差异,你不能在 Python 3 中使用 来更改函数作用域内的局部变量exec,尽管在 Python 2 中可以这样做。甚至以前声明的变量也不行。
locals()仅反映一个方向上的局部变量。以下内容在 2 或 3 中从未起作用:
def foo(): a = 'spam' locals()['a'] = 'ham' print(a) # prints 'spam'
在 Python 2 中,使用exec语句意味着编译器知道关闭局部范围优化(例如从切换到LOAD_FAST,LOAD_NAME在局部和全局范围内查找变量)。作为exec()函数,该选项不再可用,并且函数范围现在始终是经过优化的。
LOAD_FAST
LOAD_NAME
此外,在 Python 2 中,该exec语句明确地将在中找到的所有变量复制locals()回函数 locals 使用PyFrame_LocalsToFast,但前提是没有提供globals和locals参数。
PyFrame_LocalsToFast
正确的解决方法是使用一个新的命名空间(字典)进行调用exec():
def execute(a, st): namespace = {} exec("b = {}\nprint('b:', b)".format(st), namespace) print(namespace['b'])
文档对这个限制exec()说得非常明确:
注意:默认局部变量的作用如下函数所述:不应尝试locals()修改默认局部变量字典。如果您需要在函数返回后查看代码对局部变量的影响,请传递显式局部变量字典。exec()