If you need help reviewing Nonlocal, take a look at these resources:
Each question has a "Toggle Solution" button -- click it to reveal that question's solution.
Conceptual Questions
Question 1
Would this code work? If not, how would you fix it?
def make_counter():
count = 0
def counter():
count += 1
return count
return counter
No, this code would not work. Here's how we can find out:
- The line
count += 1
is equivalent tocount = count + 1
, so we rewrite it as such. - Python notices that
count
appears on the left side of an assignment statement, so Python remembers to treatcount
as a local variable. - Python then begins executing the line. To compute
count + 1
Python must look upcount
. - But Python had previously marked
count
as a local variable, and it doesn't have a value yet! So Python raises an error.
To fix it, add a nonlocal statement:
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter
Question 2
Consider the following code:
def fn1(bob):
def fn2(alice):
def fn3(alice):
def fn4():
nonlocal bob, alice
return bob + alice
return fn4
return fn3
return fn2
Answer the following questions:
- In which function's frame does Python start looking for
alice
? - In which function's frame does Python stop looking for
alice
? - In which function's frame does Python start looking for
bob
? - In which function's frame does Python stop looking for
bob
?
fn3
fn3
fn3
fn1
Question 3
Identify all the errors regarding nonlocal in the following code:
bob = 2
def fn1(bob):
eve = 3
def fn2(alice):
nonlocal bob, alice
eve = 4
return eve + alice
return fn2
nonlocal alice
is incorrect, since
alice
is already defined in the same frame (as a
parameter to fn2
).
eve = 4
will NOT cause any errors,
since eve
is not being referenced before
assignment. However, because eve
is not declared
as nonlocal, the eve
in fn1
will retain
the value of 3.
Environment Diagrams
Question 4
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter
counter = make_counter()
counter()
counter()
Question 5
def foo():
lst = []
def bar(m):
nonlocal lst
lst = lst + [m]
return lst
return bar
bar = foo()
bar(3)
bar(4)
Question 6
def foo():
lst = []
def bar(m):
lst.append(m)
return lst
return bar
bar = foo()
bar(3)
bar(4)