Note: exec
在Python 2.x中只是一个Simple语句,而在Python 3.x中它是一个函数。
Python 2.7
让我们检查执行后所做的更改a
.
class Test:
def __init__(self):
l, g = locals().copy(), globals().copy()
exec a # NOT a function call but a statement
print locals() == l, globals() == g
x()
t = Test()
Output
False True
42
这意味着,它改变了一些东西locals
字典。如果您打印locals().keys()
之前和之后exec
, 你会看见x
, after exec
。根据文档exex https://docs.python.org/2/reference/simple_stmts.html#exec,
在所有情况下,如果省略可选部分,则代码将在当前范围内执行。
因此,它完全按照文档所述进行操作。
Python 3.x:
当我们在 Python 3.x 中执行相同的操作时,我们会得到类似的结果,但会出现该错误。
class Test:
def __init__(self):
l, g = locals().copy(), globals().copy()
exec(a) # Function call, NOT a statement
print(locals() == l, globals() == g)
x()
Output
False True
NameError: name 'x' is not defined
即便是的文档exec功能 https://docs.python.org/3.5/library/functions.html#exec says,
在所有情况下,如果省略可选部分,则代码将在当前范围内执行。
但它还在底部添加了一个注释,
Note:默认局部变量的行为如函数所述locals()
below: 不应尝试修改默认的本地字典。如果您需要在函数执行后查看代码对局部变量的影响,请传递显式局部变量字典exec()
返回。
于是,我们好奇地查了一下locals()文档 https://docs.python.org/3.5/library/functions.html#locals并找到
Note:本词典的内容不得修改;更改可能不会影响解释器使用的局部变量和自由变量的值。
因此,解释器不尊重对locals()
目的。这就是为什么它不认识x
如本地范围中所定义。
但当我们这样做时
def __init__(self):
exec(a, globals())
x()
它有效,因为我们将它添加到globals
字典。 Python 试图寻找x
首先在本地范围内,然后在类范围内,然后在全局范围内,它在那里找到它。所以它执行起来没有任何问题。