在Python 3.7参考手册的Execution Model section中,我读了以下语句:
global
语句的作用域与同一块中的名称绑定操作相同。如果自由变量的最近封闭范围包含global
语句,则将自由变量视为全局变量。
因此,我在Python解释器中输入了以下代码:
x =0
def func1():
global x
def func2():
x = 1
func2()
在调用func1()
之后,我希望全局范围内的x
的值更改为1
。
我怎么了?
答案 0 :(得分:3)
x = 1
中的 func2
不是自由变量。这只是另一个当地人。除非另有说明,否则您将绑定到该名称,默认情况下,绑定的名称是本地人。
来自same Execution model documentation:
如果名称绑定在块中,则除非声明为
nonlocal
或global
,否则它是该块的局部变量。 [...] 如果在代码块中使用了变量但未在代码块中定义,则它是一个自由变量。
(粗体强调我)
您在块中用x = 1
绑定了名称,因此它是该块中的局部变量,并且不能是自由变量。因此,您发现的部分不适用,因为这仅适用于自由变量:
如果自由变量的最近封闭范围 包含
global
语句,则将自由变量视为全局变量。
您不应在x
中绑定func2()
,因为只有在范围内 not 绑定的名称才是自由变量。
这可行:
>>> def func1():
... global x
... x = 1
... def func2():
... print(x) # x is a free variable here
... func2()
...
>>> func1()
1
>>> x
1
x
中的 func2
现在是一个自由变量;它未在func2
的范围内定义,因此请从父范围中选取它。此处的父作用域为func1
,但是x
在此处被标记为全局,因此当对x
函数进行读取 print()
时,将使用全局值
与此相反,x
在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
中的func2
是一个自由变量,但是父范围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
中的 outerfunc
是绑定的,因此不是自由变量。因此,它在该范围内是本地的。但是,在func1
中,global x
声明将x
标记为嵌套scrope中的全局变量。 func2
中的x
是一个自由变量,根据您找到的语句,它被视为全局变量。