因此,Python始终会将每个函数中的每个名称归类为 local , non-local 或 global之一
。这些名称范围是排他的;在每个函数中(嵌套函数中的名称都有其自己的命名范围),每个名称只能属于这些类别之一。
当Python编译此代码时:
def fun(): if False: x=3
它将产生一个抽象的语法树,如下所示:
FunctionDef( name='fun', args=arguments(...), b body=[ If(test=NameConstant(value=False), body=[ Assign(targets=[Name(id='x', ctx=Store())], value=Num(n=3)) ], orelse=[]) ])
(为简洁起见,省略了一些内容)。现在,当将此抽象语法树编译为代码时,Python将扫描所有名称节点。如果存在
Name带有的节点,则
ctx=Store()该名称被认为是封闭的
本地 名称
FunctionDef,除非在同一函数定义中用
global(即
global x)或
nonlocal(
nonlocalx)语句覆盖该名称。
ctx=Store()主要在将名称用于赋值的左侧或在循环中用作迭代变量时,才会发生这种情况
for。
现在,当Python将其编译为字节码时,生成的字节码为
>>> dis.dis(fun) 40 LOAD_GLOBAL 0 (print) 3 LOAD_FAST 0 (x) 6 CALL_FUNCTION 1 (1 positional, 0 keyword pair) 9 POP_TOP 10 LOAD_ConST 0 (None) 13 RETURN_VALUE
优化器
if完全删除了该语句。但是,由于变量已被标记为函数的 局部 变量,因此
LOAD_FAST用于
x,这将导致只能
x从 局部
变量和局部变量进行访问。由于
x尚未设置,因此
UnboundLocalError将引发。
LOAD_GLOBAL。



