x = 1
infunc2
不是自由变量。这只是另一个本地人;默认情况下,您绑定到的名称和绑定的名称是本地人,除非您另外告诉 Python。
来自相同的执行模型文档:
如果名称绑定在块中,则它是该块的局部变量,除非声明为nonlocal
or global
。[...] 如果变量在代码块中使用但未在其中定义,则它是自由变量。
(粗体强调我的)
您用 绑定了块中的名称x = 1
,因此它是该块中的局部变量,不能是自由变量。所以你发现的部分不适用,因为那只适用于自由变量:
如果自由变量的最近封闭范围包含global
语句,则自由变量被视为全局变量。
您不应该绑定x
in func2()
,因为只有在范围内未绑定的名称才是自由变量。
所以这有效:
>>> def func1():
... global x
... x = 1
... def func2():
... print(x) # x is a free variable here
... func2()
...
>>> func1()
1
>>> x
1
x
infunc2
现在是一个自由变量;它未在 的范围内定义func2
,因此从父范围中获取。这里的父作用域是func1
,但x
在那里被标记为全局,因此在读取 x
函数时使用print()
全局值。
x
将此与未标记为全局 in 进行对比func1
:
>>> def func1():
... x = 1
... def func2():
... print(x) # x is free variable here, now referring to x in func1
... func2()
...
>>> x = 42
>>> func1()
1
这里全局名称x
设置为42
,但这不会影响打印的内容。x
infunc2
是一个自由变量,但父范围func1
仅x
作为本地名称。
当您添加一个仍然是本地的新最外层范围时,它变得更加有趣:x
>>> def outerfunc():
... x = 0 # x is a local
... def func1():
... global x # x is global in this scope and onwards
... def func2():
... print('func2:', x) # x is a free variable
... func2()
... print('outerfunc:', x)
... func1()
...
>>> x = 42
>>> outerfunc()
outerfunc: 0
func2: 42
>>> x = 81
>>> outerfunc()
outerfunc: 0
func2: 81
x
inouterfunc
是有界的,所以不是自由变量。因此,它在该范围内是本地的。但是,在 中func1
,global x
声明在嵌套的 scrope 中标记x
为全局。Infunc2
x
是一个自由变量,根据您找到的语句,它被视为全局变量。