thautwarm
2018-01-07 13:22:27 +08:00
为什么会 NameError,这是符号表加载的问题。
locals()设置新 name 是无意义的,虽然每一次在一个作用域拿出的 locals()都是同一个引用,但是导入符号并非直接使用 locals(),也就是说你对它的修改,如果是修改 mutable 对象的内部还好,直接改 immutable 自然是无效的。
Python 确定从哪里加载符号,代码编译到字节码时就确定了。既然编译时找不到 lis3 的定义,自然就认为它来自 globals()里面。而你在代码解释时才修改 locals(),那么犯错的原因,如下有俩
1. locals()不是 func 作用域加载符号所用的符号表
2. lis3 被预先认为是定义在 globals()里的。
P.S 关于 locals()的行为。
locals()其中一部分类似于一个作用域符号管理结构 S 上的 view。另一部分,locals()应该也有一个"固有成分",当你对 locals()进行__setitem__操作,并不是没有起效果,而是因为 locals 的__getitem__是有限搜索 S 的 item,没有的话再搜索 locals()的"固有成分"。
def g(x=20):
d = locals()
locals()['x'] = 10
print(locals()['x'])
print(d is locals())
g()
# => 20
# True
def g():
locals()['x'] = 10
print(locals()['x'])
g()
# 10
以上。。