A name used in a function can have only one scope for the whole function body. The scope is determined at compile time (not when the function is run).
If there's an assignment to a name anywhere in the function (regardless of whether it will be run when the function is called), the compiler will treat that name as local to the function by default. You can use the global
and nonlocal
statements to explicitly tell it to use a different scope.
A special case is where a name is assigned to in one function's body, and accessed from another function that is defined within the first function. Such a variable will be put in a special closure
cell that will be shared between the functions. The outer function will treat the variable like a local, while the inner function can only assign to it if it has a nonlocal
statement for the name. Here's an example of a closure and a nonlocal
statement:
def counter():
val = 0
def helper():
nonlocal val
val += 1
return val
return helper
In addition to the issue you're seeing, there's another sort of scope confusion that you may see:
x = 1
def foo():
print(x) # you might expect this to print the global x, but it raises an exception
x = 2 # this assignment makes the compiler treat the name x as local to the function
In the foo
function the name x
is considered a local everywhere, even though the print
call tries to use it before it has been assigned to in the local namespace.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…