如果我这样做:
newvar = raw_input()
globals()[newvar] = 4
很明显,结果变量是在运行时创建的,因为它是唯一的可能性。但是,如果我这样做:
globals()['y']=3
似乎y
也是在运行时创建的。为什么会这样?动态行为来自哪里?
答案 0 :(得分:1)
您的模块(或exec
上下文等)全局变量为dict
,而globals()
只返回dict
。之后,['y'] = 3
部分就像任何其他字典分配一样。
如果你问为什么Python没有将它优化为静态分配......好吧,想想它必须做什么。
首先,检测'y'
是一个文字很容易;这些信息就在AST中。
但是检测到dict
是你模块的全球词典要困难得多。 globals
不是关键字或其他任何神奇的关键字,它只是builtins
中的常规功能。您可以使用全局,非本地或本地名称或monkeypatch builtins
隐藏它,甚至可以替换全局变量的内置函数,因此无法访问它。因此,它必须进行充分的分析,以确定globals
上的名称查找除了适当的全局字典之外不可能返回任何内容。
并且,不仅如此,为了使其有用,语言必须要求每个实现进行相同的优化。否则,您可以根据优化是否发生,从某些程序中获得不同的语义。
同样值得记住的是,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