在Python中,globals()
返回全局符号表的表示,而locals()
返回本地状态的表示。虽然两者都返回字典,但对globals()
的更改会在全局符号表中生效,而对locals()
的更改则无效。
为什么会这样?
答案 0 :(得分:7)
函数本地是高度优化的,并且在编译时确定,CPython建立在无法在运行时动态更改已知本地的位置。
解码函数字节码时可以看到这一点:
>>> import dis
>>> def foo():
... a = 'bar'
... return a + 'baz'
...
>>> dis.dis(foo)
2 0 LOAD_CONST 1 ('bar')
3 STORE_FAST 0 (a)
3 6 LOAD_FAST 0 (a)
9 LOAD_CONST 2 ('baz')
12 BINARY_ADD
13 RETURN_VALUE
LOAD_FAST
和STORE_FAST
操作码使用 indices 来加载和存储变量,因为在一个帧上本地实现为数组。访问数组比使用哈希表(字典)更快,例如用于全局命名空间。
locals()
函数在函数中使用时,会将此数组的反射作为字典返回。改变locals()
字典将不会将其反映回数组中。
在Python 2中,如果在代码中使用exec
语句,则优化(部分)被破坏;在这种情况下,Python使用较慢的LOAD_NAME
opcode:
>>> def bar(code):
... exec code
... return a + 'baz'
...
>>> dis.dis(bar)
2 0 LOAD_FAST 0 (code)
3 LOAD_CONST 0 (None)
6 DUP_TOP
7 EXEC_STMT
3 8 LOAD_NAME 0 (a)
11 LOAD_CONST 1 ('baz')
14 BINARY_ADD
15 RETURN_VALUE
另见bug report against Python 3其中exec()
(Py3中的函数)不允许再设置本地名称:
要动态修改函数的局部变量不是 可能没有几个后果:通常,函数本地人不是 存储在字典中,但是一个数组,其索引是在 从已知语言环境编译时间。这至少与新的碰撞 本地人由exec添加。 旧的执行声明绕过了这个,因为 编译器知道如果没有globals / locals的exec发生了 在一个函数中,该命名空间将是“未优化的”,即不使用 locals array。由于exec()现在是一个普通的函数,编译器就是这样 不知道“exec”可能会受到什么约束,因而无法对待 特别