您可以从的范围中看到
b有关自由变量(可用于绑定)的了解范围
a,如下所示:
import inspectprint( "let's begin" )def a(): if False: x = 10 def b(): print(inspect.currentframe().f_pre.co_freevars) nonlocal x x = 20 b()a()
这使:
let's begin('x',)如果您注释掉该
nonlocal行,并删除其中的
if语句,
x则会看到可供使用的自由变量
bis
()。
因此,让我们看一下它生成的字节码指令,方法是将的定义
a放入IPython中,然后使用
dis.dis:
In [3]: import disIn [4]: dis.dis(a) 50 LOAD_CLOSURE 0 (x) 2 BUILD_TUPLE 1 4 LOAD_ConST 1 (<pre object b at 0x7efceaa256f0, file "<ipython-input-1-20ba94fb8214>", line 5>) 6 LOAD_ConST 2 ('a.<locals>.b') 8 MAKE_FUNCTION 8 10 STORE_FAST 0 (b) 10 12 LOAD_FAST 0 (b) 14 CALL_FUNCTION 0 16 POP_TOP 18 LOAD_ConST 0 (None) 20 RETURN_VALUE因此,让我们看一下如何
LOAD_CLOSURE处理
ceval.c。
TARGET(LOAD_CLOSURE) { PyObject *cell = freevars[oparg]; Py_INCREF(cell); PUSH(cell); DISPATCH();}因此,我们看到它必须
x从
freevars封闭的范围中查找。
执行模型文档中提到了这一点,其中说:
nonlocal语句使对应的名称引用最近的封闭函数范围中的先前绑定的变量。如果给定名称在任何封闭函数范围中不存在,则 在编译时
引发SyntaxError 。



