python的exec函数的奇怪行为

时间:2012-07-25 21:35:48

标签: python

我认为下面的代码完全描述了这个问题。为什么在Test2函数x中没有定义?为什么Test3函数不会返回错误?

>>> def Test1():
exec('x=2')
print(str(x))


>>> Test1()
2
>>> def Test2():
global x
exec('x=2')
print(str(x))


>>> Test2()

Traceback (most recent call last):
File "<pyshell#39>", line 1, in <module>
Test2()
File "<pyshell#38>", line 4, in Test2
print(str(x))
NameError: global name 'x' is not defined

>>> def Test3():
global x
x=2
print(str(x))

>>> Test3()
2

2 个答案:

答案 0 :(得分:3)

在函数Test2中,当您声明global x时,您声明x是一个全局变量,因此Python将在全局命名空间中搜索它。 由于全局命名空间中没有定义x变量,因此会引发NameError

如果您阅读the official documentation,则可以看到eval功能不受global声明影响,因此在Test2 exec正在创建名为x的新局部变量,值为2,但不是全局变量; printglobal语句的影响,并在不存在的全局命名空间中搜索x。在Test3中,x=2语句受global语句的影响,从而创建一个名为x的全局变量,值为2.

答案 1 :(得分:2)

@SanSS给出的答案是正确的,正如@Colin Dunklau的评论一样,但我想补充一点信息。可能会让您失望的一件事是Test2中的global x 继续执行执行代码。因此,exec创建本地变量x,而print x尝试读取全局变量。这两个例子可能会有所帮助。 。

这里通过传递一个dict,你告诉exec使用它作为全局本地,所以exec分配给全局:

>>> def Test2():
...     global x
...     exec 'x=2' in globals()
...     print(str(x))
>>> Test2()
2

这里通过在exec-ed代码中包含全局声明,将exec赋值给global,然后print语句读取:

>>> def Test2():
...     global x
...     exec('global x; x=2')
...     print(str(x))
>>> Test2()
2

然而,重申一下,使用exec通常不是一个好主意。有时只是为了理解Python是如何工作的,可以很好地利用这样的东西,但是在很少的情况下,这是用你的代码实际完成某些事情的好方法。