7

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() 的文档中,或者可能隐藏在其他类似的问题中,但我认为值得将这种表现形式提出来。

我很想了解 Python 解释器在这里的想法,以及解决方法的建议。

4

2 回答 2

2

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

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

如果您阅读Eli Bendersky 的这篇精彩文章中的符号表是如何处理的,您可以更好地理解局部变量是如何处理的。

您不应该使用exec这种代码(我希望这不是生产代码),并且当您将代码移植到 Py3k 时它无论如何都会中断:

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


或许我应该直奔主题:

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

def f():
    data = {'a': 1}
    data['a'] = 2
    if ...:
        data['a'] = 3
于 2012-09-18T20:50:57.037 回答
1

来自locals功能文档

注意:不得修改本词典的内容;更改可能不会影响解释器使用的局部变量和自由变量的值。

检查:

>>> def f():
    a = 1
    print(locals())
    locals()['a']=2
    print(a,locals())


>>> f()
{'a': 1}
1 {'a': 1}

所以你不能通过locals()函数修改本地上下文

于 2012-09-18T20:55:24.010 回答