Python 2和Python 3中的exec函数的行为
以下代码在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函数中的variablesb绑定到exec函数string中的值,而Python3不这样做? 我如何在Python3实现Python2的行为? 我已经尝试将globals和locals的字典传递给Python3 exec函数,但目前为止还没有任何工作。 
—编辑—
 在阅读Martijns的答案后,我进一步用Python3分析了这个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来更改函数范围中的局部variables,尽pipe在Python 2中是可能的。甚至没有先前声明的variables。 
 局部variableslocals()只反映局部variables的方向。 以下从未在2或3工作: 
 def foo(): a = 'spam' locals()['a'] = 'ham' print(a) # prints 'spam' 
 在Python 2中,使用exec语句意味着编译器知道closures本地范围优化(例如,从LOAD_FAST切换到LOAD_NAME ,以便在本地和全局范围内查找variables)。 用exec()函数,该选项不再可用,函数作用域现在总是被优化。 
 此外,在Python 2中, exec语句将使用PyFrame_LocalsToFast将所有在locals()find的variables显式复制到函数本地,但PyFrame_LocalsToFast是不提供全局variables和PyFrame_LocalsToFast variables参数。 
 正确的解决方法是为你的exec()调用使用一个新的命名空间(一个字典): 
 def execute(a, st): namespace = {} exec("b = {}\nprint('b:', b)".format(st), namespace) print(namespace['b']) 
我会说这是一个python3的错误。
 def u(): exec("a=2") print(locals()['a']) u() 
打印“2”。
 def u(): exec("a=2") a=2 print(a) u() 
打印“2”。
但
 def u(): exec("a=2") print(locals()['a']) a=2 u() 
失败
 Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in u KeyError: 'a' 
—编辑—另一个有趣的行为:
 def u(): a=1 l=locals() exec("a=2") print(l) u() def u(): a=1 l=locals() exec("a=2") locals() print(l) u() 
输出
 {'l': {...}, 'a': 2} {'l': {...}, 'a': 1} 
并且
 def u(): l=locals() exec("a=2") print(l) print(locals()) u() def u(): l=locals() exec("a=2") print(l) print(locals()) a=1 u() 
输出
 {'l': {...}, 'a': 2} {'l': {...}, 'a': 2} {'l': {...}, 'a': 2} {'l': {...}} 
 显然, exec对当地人的行为如下: 
-  如果在exec设置了一个variables,并且这个variables是一个局部variables,那么exec会修改内部字典(locals()返回的字典),并且不会将其返回到原始状态。 对locals()调用更新字典(如python文档的第2部分所述),并且exec设置的值被遗忘。 调用locals()来更新字典的需求并不是python3的一个bug,因为它被logging下来,但它并不直观。 此外,exec中的局部variables不会改变函数的局部variables这一事实与python2是有文档上的区别的(文档中提到“如果需要在函数执行后查看代码对本地代码的影响,传递一个显式的局部variables字典)返回“),我更喜欢python2的行为。
-  如果在exec设置了一个variables,并且此variables之前不存在,那么exec将修改内部字典,除非该variables是事后设置的。 似乎locals()更新字典的方式有一个错误; 这个bug通过在exec后调用locals()来访问exec设置的值。
 恐怕我不能正确地解释它,但它基本上来自于函数内部的b是本地的,而exec()似乎是分配给全局b的事实。 你必须在函数内声明b是全局的, 并且在exec语句中。 
尝试这个:
 from sys import version print(version) def execute1(a, st): b = 42 exec("b = {}\nprint('b:', b)".format(st)) print(b) def execute2(a, st): global b b = 42 exec("global b; b = {}\nprint('b:', b)".format(st)) print(b) a = 1. execute1(a, "1.E6*a") print() execute2(a, "1.E6*a") print() b = 42 exec("b = {}\nprint('b:', b)".format('1.E6*a')) print(b) 
这给了我
 3.3.0 (default, Oct 5 2012, 11:34:49) [GCC 4.4.5] b: 1000000.0 42 b: 1000000.0 1000000.0 b: 1000000.0 1000000.0 
你可以看到,在这个函数之外,全局b被自动拾取。 在函数内部,你正在打印本地b。
 请注意,我以为exec()总是首先使用全局b,所以在execute2() ,你不需要在exec()函数内声明它。 但我发现这是行不通的(这是我无法解释的部分)。