如果我这样做:
newvar = raw_input()
globals()[newvar] = 4
很明显,生成的变量是在运行时创建的,因为这是唯一的可能性。然而,如果我这样做:
globals()['y']=3
似乎y
也是在运行时创建的。为什么会这样?动态行为从何而来?
附言:我知道这是一种不好的做法,我只是想了解一下。
您的模块(或exec
上下文等)的全局是dict
,而globals()
只返回该dict
。之后,['y'] = 3
部分就像任何其他字典分配一样。
如果你问Python为什么不将其优化为静态分配……那么,想想它必须做什么。
首先,检测'y'
是一个文字非常容易;该信息就在AST中。
但是检测dict
是模块的全局字典要困难得多。globals
不是一个关键字或任何其他神奇的东西,它只是builtins
中的一个常规函数。您可以用全局、非本地或本地名称或monkeypatch builtins
隐藏它,甚至可以替换全局的内置名称,使其不可访问。因此,它必须进行充分的分析,以确定在globals
上的名称查找不可能返回任何内容,而只能返回适当的全局dict
不仅如此,为了使这一点变得有用,该语言必须要求每个实现都进行相同的优化。否则,根据是否进行了优化,您可以从一些程序中获得不同的语义。
同样值得记住的是,CPython除了基本的窥视孔优化之外没有做任何事情,因此您必须从头开始为更复杂的优化器构建基础设施,只需添加一个小的更改。
除此之外,对同一全局字典的引用存储在各处。因此,即使进行了这种优化,您仍然可以同样轻松地欺骗Python:
g = globals()
g['y'] = 3
globals().__getitem__('globals')()['y'] = 3
def f(): pass
f.__globals__['y'] = 3
inspect.currentframe().f_globals['y'] = 3