我无法找到这种行为的充分解释。
>>> def a():
... foo = 0
... print locals()
... def b():
... print locals()
... b()
>>> a()
{'foo': 0}
{}
可是:
>>> def a():
... foo = 0
... print locals()
... def b():
foo
... print locals()
... b()
>>> a()
{'foo': 0}
{'foo': 0}
据我所知,在第二种情况下有一个闭包,但我找不到实际内容的详细描述,在什么条件下应返回函数locals()
。
答案 0 :(得分:5)
如果您未在关闭内分配给foo
,则Python会将其解析为范围的foo
一级(并且直至找到foo
在某处或抛出异常)。
在第二个示例中提到foo
中的b()
,您将foo
放入b()
内的本地人,但它会解析为foo
内的a()
foo = 1
的正文。如果您在b()
中指定 {'foo': 0}
{'foo': 1}
,则会看到
{{1}}
作为输出。
答案 1 :(得分:3)
locals()内置函数打印绑定到代码对象的本地符号表,并在解释器收到源代码中的名称时填充。
第二个例子,当反汇编时,将在 b 功能代码中包含 LOAD_GLOBAL foo 字节码指令。这个LOAD_GLOBAL指令将向上移动范围,找到外部foo名称并通过将名称偏移量添加到闭包(函数b)代码对象的 co_names 属性中将其绑定到代码对象。
locals()函数打印本地符号表(如前所述,函数代码对象的co_names属性)。
详细了解代码对象here。