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 解释器在这里的想法,以及解决方法的建议。
旧的Python 2的exec
将更改字节码以搜索本地和全局命名空间。
当您在全局中定义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
来自locals
函数文档:
注意:不应修改此字典的内容;更改可能不会影响解释器使用的局部变量和自由变量的值。
检查:
>>> def f():
a = 1
print(locals())
locals()['a']=2
print(a,locals())
>>> f()
{'a': 1}
1 {'a': 1}
所以你不能通过locals()
函数修改局部上下文