[英]Free variables treated as globals in Python?
In the Execution Model section of the Python 3.7 reference manual I read the following statement: 在Python 3.7参考手册的“ 执行模型”部分中,我阅读了以下语句:
The
global
statement has the same scope as a name binding operation in the same block.global
语句的作用域与同一块中的名称绑定操作相同。 If the nearest enclosing scope for a free variable contains aglobal
statement, the free variable is treated as a global.如果最接近的自由变量包围范围包含
global
语句,则将自由变量视为global
语句。
So I typed the following code into the Python Interpreter: 因此,我在Python解释器中输入了以下代码:
x =0
def func1():
global x
def func2():
x = 1
func2()
After calling func1()
I would have expected the value of x
in the global scope to change to 1
. 调用
func1()
我希望全局范围内的x
值更改为1
。
What did I get wrong? 我怎么了?
x = 1
in func2
is not a free variable . func2
x = 1
不是自由变量 。 It's just another local; 这只是另一个当地人。 you are binding to the name and names bound to are, by default, locals unless you tell Python otherwise.
您将绑定到该名称,默认情况下,绑定的名称是本地人,除非您另行告诉Python。
From the same Execution model documentation : 从相同的执行模型文档中 :
If a name is bound in a block, it is a local variable of that block, unless declared as
nonlocal
orglobal
.如果名称绑定在块中,则除非声明为
nonlocal
或global
,否则它是该块的局部变量。 [...] If a variable is used in a code block but not defined there, it is a free variable.[...] 如果变量在代码块中使用但未在代码块中定义,则它是一个自由变量。
( Bold emphasis mine ) ( 加粗强调我的 )
You bound the name in the block with x = 1
, so it is a local variable in that block, and can't be a free variable. 您将块中的名称与
x = 1
绑定在一起,因此它是该块中的局部变量,并且不能是自由变量。 So section you found doesn't apply, because that would only apply to free variables: 因此,您发现的部分不适用,因为这仅适用于自由变量:
If the nearest enclosing scope for a free variable contains a
global
statement, the free variable is treated as a global.如果最接近的自由变量包围范围包含
global
语句,则将自由变量视为global
语句。
You should not bind x
in func2()
, because only names that are not binding in the scope are free variables. 您不应在
func2()
绑定x
,因为只有未在范围内绑定的名称才是自由变量。
So this works: 所以这有效:
>>> def func1():
... global x
... x = 1
... def func2():
... print(x) # x is a free variable here
... func2()
...
>>> func1()
1
>>> x
1
x
in func2
is now a free variable; func2
x
现在是一个自由变量; it is not defined in the scope of func2
, so picks it up from the parent scope. 它不是在
func2
的范围内定义的,因此请从父范围中选择它。 The parent scope here is func1
, but x
is marked a global there so when reading x
for the print()
function the global value is used. 此处的父作用域是
func1
,但是x
被标记为全局范围,因此当为print()
函数读取 x
,将使用全局值。
Contrast this with x
not being marked as a global in func1
: 与此相反,
x
在func1
没有被标记为全局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
Here the global name x
is set to 42
, but this doesn't affect what is printed. 此处,全局名称
x
设置为42
,但这并不影响打印的内容。 x
in func2
is a free variable, but the parent scope func1
only has x
as a local name. func2
中的x
是一个自由变量,但父作用域func1
仅将x
作为本地名称。
It becomes all the more interesting when you add a new outer-most scope where x
is still local : 当您添加新的最外部作用域(其中
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
in outerfunc
is bound, so not a free variable. x
中的outerfunc
是有界的,因此不是自由变量。 It is therefore a local in that scope. 因此,它在该范围内是本地的。 However, in
func1
, the global x
declaration marks x
as a global in the nested scrope. 然而,在
func1
,在global x
声明标记x
作为嵌套斯克罗普一个全球性的。 In func2
x
is a free variable, and by the statement that you found, it is treated as a global. 在
func2
x
是一个自由变量,根据找到的语句,它被视为全局变量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.