From the Google Style Guide on lexical scoping:
A nested Python function can refer to variables defined in enclosing functions, but can not assign to them.
Both of these seem to check out at first:
# Reference
def toplevel():
a = 5
def nested():
print(a + 2)
nested()
return a
toplevel()
7
Out[]: 5
# Assignment
def toplevel():
a = 5
def nested():
a = 7 # a is still 5, can't modify enclosing scope variable
nested()
return a
toplevel()
Out[]: 5
So why, then, does a combination of both reference and assignment in the nested function lead to an exception?
# Reference and assignment
def toplevel():
a = 5
def nested():
print(a + 2)
a = 7
nested()
return a
toplevel()
# UnboundLocalError: local variable 'a' referenced before assignment
In first case, you are referring to a nonlocal
variable which is ok because there is no local variable called a
.
def toplevel():
a = 5
def nested():
print(a + 2) # theres no local variable a so it prints the nonlocal one
nested()
return a
In the second case, you create a local variable a
which is also fine (local a
will be different than the nonlocal one thats why the original a
wasn't changed).
def toplevel():
a = 5
def nested():
a = 7 # create a local variable called a which is different than the nonlocal one
print(a) # prints 7
nested()
print(a) # prints 5
return a
In the third case, you create a local variable but you have print(a+2)
before that and that is why the exception is raised. Because print(a+2)
will refer to the local variable a
which was created after that line.
def toplevel():
a = 5
def nested():
print(a + 2) # tries to print local variable a but its created after this line so exception is raised
a = 7
nested()
return a
toplevel()
To achieve what you want, you need to use nonlocal a
inside your inner function:
def toplevel():
a = 5
def nested():
nonlocal a
print(a + 2)
a = 7
nested()
return a
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments