赋值顺序意外地与“globals(),locals()中的exec expr”有关。

时间:2012-09-18 20:43:26

标签: python global-variables eval

Python 2.X中的以下代码按照您的预期打印“a:2”:

def f():
  #a = 1
  exec "a = 2" in globals(), locals()
  for k,v in locals().items(): print k,":",v
  #a = 3

f()

但如果你取消注释“a = 1”,那么就会打印出“a:1”,正如我没想到的那样。 甚至更奇怪,如果你取消注释“a = 3”线,那么它根本不打印任何东西,我绝对没想到(我有一个令人困惑的错误,我提炼到那个)。

我认为答案隐藏在locals()和globals()的文档中,或者可能在其他问题like this中,但我认为值得将此表现出来。

我很想知道Python解释器在这里想到的是什么,以及解决方法的建议。

1 个答案:

答案 0 :(得分:2)

旧的Python 2 exec会更改字节码以搜索本地名称空间和全局名称空间。

当您在全局中定义a = 2时,这是在a = 1被评论时找到的那个。取消注释a = 3后,这是a“找到”但尚未定义。

如果您阅读了如何在此great article by Eli Bendersky中处理符号表,您可以更好地了解如何处理局部变量。

您不应该将exec用于此类代码(我希望这不是生产代码),并且当您将代码移植到Py3k时它会中断:

Python 3的exec函数不再是一个语句,因此无法改变它所处的环境。


可能我应该直截了当地说:

如果你正在做所有这些动态命名的东西,你应该使用字典:

def f():
    data = {'a': 1}
    data['a'] = 2
    if ...:
        data['a'] = 3