问题
Why is the following code invalid:
def foo1(x=5):
def bar():
if x == 5:
x = 6
print(x)
bar()
While this code is valid:
def foo2(x=5):
def bar():
if x == 5:
print('ok')
print(x)
bar()
foo2()
will do exactly what you expect, but foo1()
will give a UnboundLocalError: local variable 'x' referenced before assignment
at the line if x == 5:
. Why does altering the value of x later on in the code make this conditional invalid?
回答1:
Python needs first to detect what variables are local, and which variable are fetched from an outer scope. In order to do that it looks for assignments, like:
def foo1(x=5):
def bar():
if x == 5:
x = 6 # an assignment, so local variable
print(x)
bar()
The point is, that the assignment can happen anywhere. For instance on the last line. Nevertheless, from the moment there is an assignment somewhere x
is local. So in your first code fragment, x
is a local variable. But you fetch it before it is assigned (bounded), so Python will error on it.
In python-3.x you can use the nonlocal
keyword to access x
from an outer scope:
def foo1(x=5):
def bar():
nonlocal x
if x == 5:
x = 6
print(x)
bar()
For python-2.x, you can for instance assign the variable to the function, like:
def foo1(x=5):
def bar():
if bar.x == 5:
bar.x = 6
print(bar.x)
bar.x = x
bar()
Note however that the two are not equivalent. Since in the former if you alter x
, it will be alter the x
in the foo1
scope as well. In the latter example you only modify bar.x
. Of course if these are mutable objects, you alter the same object.
来源:https://stackoverflow.com/questions/44616882/nested-function-definitions-and-scope-unboundlocalerror