2014-09-20 133 views
0

的修改动态创建。如果我这样做:的变量和全局()

newvar = raw_input() 
globals()[newvar] = 4 

很明显,产生的变量在运行时创建的,只是因为这是唯一的可能性。但是,如果我这样做:

globals()['y']=3 

看起来y也是在运行时创建的。为什么会这样?动态行为来自哪里? PS:我知道这是一种不好的做法,我只是想明白。

+0

因为'globals'是一个简单的变量名在这里,如果你的名字你的任何变量'globals'什么。这就是'exec'在Python 2(关键字)和3(函数)中工作方式不同的原因。 – 2014-09-20 23:52:07

回答

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