简体   繁体   中英

Strange behavior of python's exec function

I think that below code fully describes the problem. Why in the Test2 function x has not been defined? Why the Test3 function does not return an error?

>>> 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

In function Test2 , when you declare global x you are stating that x is a global variable, so Python will search for it in the global namespace. As there is no x variable defined in the global namespace the NameError is raised.

If you read the official documentation you can see that the eval function is not affected by the global statement, so in Test2 the exec is creating a new local variable named x with value 2, but not global; the print is affected by the global statement and searches for the x in the global namespace where it doesn't exist. In Test3 the x=2 statement is affected by the global statement thus creating a global variable named x with value 2.

The answer given by @SanSS is correct, as is the comment by @Colin Dunklau, but I wanted to add a bit more info. One thing that may trip you up is that the global x in Test2 does not carry through to the exec-ed code. So the exec creates a local variable x , while the print x tries to read a global variable. These two examples may be helpful. . .

Here by passing one dict, you tell exec to use that as globals and locals, so the exec assigns to globals:

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

Here by including the global declaration in the exec-ed code, you make the exec assign to the global, which the print statement then reads:

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

To reiterate, however, it's usually not a good idea to use exec . It can be good to play around with stuff like this sometimes just to understand how Python works, but there are few cases where this is a good way to actually accomplish something with your code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM