的修改动态创建。如果我这样做:的变量和全局()
newvar = raw_input()
globals()[newvar] = 4
很明显,产生的变量在运行时创建的,只是因为这是唯一的可能性。但是,如果我这样做:
globals()['y']=3
看起来y
也是在运行时创建的。为什么会这样?动态行为来自哪里? PS:我知道这是一种不好的做法,我只是想明白。
的修改动态创建。如果我这样做:的变量和全局()
newvar = raw_input()
globals()[newvar] = 4
很明显,产生的变量在运行时创建的,只是因为这是唯一的可能性。但是,如果我这样做:
globals()['y']=3
看起来y
也是在运行时创建的。为什么会这样?动态行为来自哪里? PS:我知道这是一种不好的做法,我只是想明白。
您的模块(或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
因为'globals'是一个简单的变量名在这里,如果你的名字你的任何变量'globals'什么。这就是'exec'在Python 2(关键字)和3(函数)中工作方式不同的原因。 – 2014-09-20 23:52:07