last_called = None
The object named last_called
is immutable. To change the content of the
object will release the object and assign a new object.
print(last_called)
Looks like debugging code. last_called
is seen as the immutable object which
has not been declared as a nonlocal name yet.
# nonlocal last_called
Even if you uncommented this line, it is after the access of lasted_call
by the use of the previous print
. This is too late to change the scope.
last_called = now
This is assignment. The print(last_called)
references None
in a
different scope and the object is immutable and now attempt to assign a value to it.
The elapsed
function wants to access the immutable object named last_called
.
The interpreter progresses to the assignment and cannot continue.
Exception is raised.
Possible options for the behavior of last_called
within elapsed
:
If nonlocal last_called
is used, then declare before access and assignment.
if nonlocal last_called
is not declared, then access before assignment causes
an exception.
if nonlocal last_called
is not declared, access after assignment uses
a local name last_called
.
Your code order may work better as:
import time
def make_timer():
last_called = None
def elapsed():
now = time.time()
nonlocal last_called # declare scope
print(last_called) # access
if last_called is None: # access
last_called = now # assign
return None
elapsed_time = now - last_called # access
last_called = now # assign
return elapsed_time
return elapsed
nonlocal last_called
is uncommented as it is required for option 1.