以下代码在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将函数b内部的变量绑定到execute函数字符串中的exec值,而Python3却不这样做呢?如何实现Python2in 的行为Python3?我已经尝试过通过字典让全局变量和本地变量在中exec起作用Python3,但到目前为止没有任何效果。
execute
exec
Python2in
-编辑-
在阅读Martijns的答案之后,我用进行了进一步分析Python3。在下面的例子中,我给了locals()百科作为d到exec,但d['b']打印的东西不仅仅是打印别的b。
Martijns
locals()
d
d['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
id的比较d和locals()显示,它们是相同的对象。但在这些条件下b应与相同d['b']。我的例子有什么问题?
id
b
exec在Python 2和exec()Python 3之间有很大的不同。你将其exec视为函数,但这实际上是Python 2中的一条语句。
exec()Python 3
由于存在这种差异,exec即使在Python 2中也无法使用来更改Python 3中函数范围内的局部变量。
locals()仅在一个方向上反映局部变量。以下内容从未在2或3中起作用:
def foo(): a = 'spam' locals()['a'] = 'ham' print(a) # prints 'spam'
在Python 2,使用exec的语句意味着编译器知道(从开关关闭本地范围优化LOAD_FAST到LOAD_NAME例如,查找变量在本地和全球范围两者)。随着exec()作为一个功能,该选项不再可用,现在功能作用域总是优化。
exec()
此外,在Python 2中,该exec语句仅使用()未提供globals和locals参数,才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()文档非常明确: