locals()
更新并返回表示当前本地符号表的字典。 在函数代码块但不是类代码块中调用 locals() 时将返回自由变量。 请注意在模块层级上,locals() 和 globals() 是同一个字典。
注解 不要更改此字典的内容;更改不会影响解释器使用的局部变量或自由变量的值。
关于 locals() 的创建过程,locals() 字典是局部命名空间的代理,它会采集局部作用域的变量,代码运行期若动态修改局部变量,只会影响该字典,并不会影响真正的局部作用域的变量。因此,当再次调用 locals() 时,由于重新采集,则动态修改的内容会被丢弃。
运行期的局部命名空间不可改变,这意味着 exec() 函数中的变量赋值不会对它产生影响,但 locals() 字典是可变的,会受到 exec() 函数的影响。
关于函数的编译,Python 在编译时就确定了局部作用域内合法的变量名,在运行时再与内容绑定。作用域内变量的解析跟它的执行顺序无关,更与是否会被执行无关。
例1
def foo():
exec(‘y=1+1’)
y = locals()[‘y’]
print(y)
foo()
#KeyError: ‘y’
y = locals()[‘y’] 语句中由于exec()不会改变局部命名空间的变量,所以 locals()不会获取到exec(‘y=1+1’)动态执行时y的复制操作。
接下来的 y = locals()[‘y’]才是对y的声明和赋值,会获取等号右边的公式的值,字典取值会找y的值,因为局部作用域内有变量y的声明,因此到局部命名空间中找y的值,依赖左侧的y完成赋值,接着匹配这个key对应的值,也即y所绑定的值(即等号右边的结果)。
结论:右边的值依赖它本事,可以理解为死锁
涉及到python命名空间和作用域的规则:
python解释器动态执行过程中,对遇到的变量进行解释时,是按照一条固定的作用域链查找解释的,又称为LEGB法则。其中L代表Local 局部作用域,E代表Enclosing 嵌套作用域,G代表Global 全局作用域,B代表Built-in 内建作用域。
globals()
返回表示当前全局符号表的字典。这总是当前模块的字典(在函数或方法中,不是调用它的模块,而是定义它的模块)。