无法通过exec()语句在函数中更改全局变量?

27 投票
4 回答
17925 浏览
提问于 2025-04-15 18:08

为什么我不能在函数内部通过exec()来改变全局变量?当赋值语句在exec()外面时,一切都正常。下面是我遇到的问题的例子:

>>> myvar = 'test'
>>> def myfunc():
...     global myvar
...     exec('myvar = "changed!"')
...     print(myvar)
... 
>>> myfunc()
test
>>> print(myvar)
test

4 个回答

4

这样怎么样:

>>> myvar = 'test'
>>> def myfunc():
...     exec('globals()["myvar"] = "changed!"')
...     print(myvar)
... 
>>> myfunc()
changed!
>>> print(myvar)
changed!

在Python 2.6中,这对我有效。

补充:其实Alex Martelli的解释比我的要好得多 :)

5

补充一下Alex的回答:虽然当你省略locals和globals参数时,它们默认使用调用者的locals和globals,但这只是一个方便的小技巧;这并不意味着它们会完全继承调用者的执行环境。特别是:

a. 嵌套作用域的变量在执行的代码中是无法访问的。所以这段代码会失败:

def f():
    foo= 1
    def g():
        exec('print foo')
    g()
f()

b. global声明不会传递到执行的代码中。因此,像你例子中的情况,写入的变量会放在locals字典里。不过,你可以通过这样做来让它生效:

exec('global myvar\nmyvar = "changed!"')

如果可以的话,你其实不太想这样做。global本身就不太好,而exec几乎算是一种代码异味!除非真的没有其他选择,否则你不想把它们结合在一起。

41

根据文档exec语句可以接受两个可选的表达式,默认情况下是 globals()locals(),而且总是会在 locals() 中进行更改(如果有的话)。

所以,记得要更明确/具体/精确一些……:

>>> def myfunc():
...   exec('myvar="boooh!"', globals())
... 
>>> myfunc()
>>> myvar
'boooh!'

…这样你就可以随心所欲地修改全局变量了。

撰写回答