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

发布于 2024-08-18 08:29:57 字数 282 浏览 3 评论 0原文

为什么我不能使用 exec() 从函数内部更改全局变量?当赋值语句位于 exec() 之外时,它可以正常工作。这是我的问题的一个例子:

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

Why can I not change global variables from inside a function, using exec()? It works fine when the assignment statement is outside of exec(). Here is an example of my problem:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

调妓 2024-08-25 08:29:57

根据文档exec语句采用两个可选表达式,默认为 globals()locals(),并且始终在 locals() 中执行更改(如果有)一。

所以,只要更明确/具体/精确......:

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

......你就能够将全局变量打乱到你的心里。

Per the docs, the exec statement takes two optional expressions, defaulting to globals() and locals(), and always performs changes (if any) in the locals() one.

So, just be more explicit/specific/precise...:

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

...and you'll be able to clobber global variables to your heart's contents.

清泪尽 2024-08-25 08:29:57

添加到亚历克斯的答案:虽然当你省略本地/全局参数时,它们默认为调用者的本地和全局参数,但这只是一个方便的黑客;它确实意味着它们正在继承调用者的完整执行上下文。特别是

:嵌套作用域单元不可用于执行的代码。所以这失败了:

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

b。 global 声明不会延续到执行的代码中。因此,默认情况下,如您的示例所示,写入的变量将放入本地字典中。 使其发挥作用

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

但是,您可以通过说“如果您能帮助的话,您实际上不想这样做”来 。 global 已经不太好了,exec 本身就是一种代码味道!除非确实别无选择,否则您不会想将它们结合起来。

To add to Alex's answer: although when you omit the locals/globals arguments they default to the locals and globals of the caller, this only a convenience hack; it does not mean they are inheriting the full execution context of the caller. In particular:

a. nested scope cells are not available to the execed code. So this fails:

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

b. global declarations do not carry over into the execed code. So by default as in your example, written variables are put in the locals dictionary. However, you could make it work by saying

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

You don't really want to be doing this if you can help it. global already isn't nice and exec is pretty much a code smell in itself! You wouldn't want to combine them unless there was really no alternative.

时光清浅 2024-08-25 08:29:57

怎么样:

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

它在 Python 2.6 中对我有用。

编辑:实际上 Alex Martelli 的解释比我的好得多:)

How about this:

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

It worked for me in Python 2.6.

EDIT: Actually Alex Martelli's explanation is much better than mine :)

深海蓝天 2024-08-25 08:29:57

根据 exec 文档,以及代码字符串有两个可选参数:全局变量和局部变量。文档解释道:

如果省略可选部分,则代码在当前范围内执行。

要改变全局变量,只需传递一个参数:

如果仅提供全局变量,它将...将用于全局变量和局部变量。

这是如何影响 exec 代码字符串中定义的函数的示例:

exec_text = """
foo = "abc"
def func2():
  if foo:
      print("yes")
func2()
"""

def func1():
    exec(exec_text, globals()) # Without globals(), this fails with: NameError: name 'foo' is not defined
func1()

Per the exec docs, along with the code string it takes two optional parameters for globals and locals. The docs explains:

if the optional parts are omitted, the code is executed in the current scope.

To mutate globals, pass just one parameter:

If only globals is provided, it ... will be used for both the global and the local variables.

An example of how this affects functions defined inside the exec code string:

exec_text = """
foo = "abc"
def func2():
  if foo:
      print("yes")
func2()
"""

def func1():
    exec(exec_text, globals()) # Without globals(), this fails with: NameError: name 'foo' is not defined
func1()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文