Section 4.8 Variables and parameters are local
As has been discussed previously, when we use variables we have to first use assignment statements to create them and initialize with a value. Similarly, we define functions in the code before the code can invoke them. Computer science uses the term
scope to describe where/when an identified item (like a variable, a function etc.) is recognizable and accessible. Calling a function or using a variable before its definition or assignment will trigger a runtime error because the item is outside of the programโs scope at that moment.
Scope becomes an even more important issue when large problems are decomposed with functions. Within a function, its parameters (and any other variable defined in the functionโs body) can only be accessed by code within the same scope. These
local variables only exists inside the function and you cannot use them outside of them. For example, consider the following version of the
square
function:
Note 4.8.1.
Weโve omitted the docstring, type annotations, and have used non-self-documenting names in the following example on purpose, to put you into a similar position as the codeโs interpreter - it can only โdoโ what the code tells it to and cannot โknowโ what it is supposed to do. But it will follow the scope rules.
Trace the code manually first. Make note of which variables are โinsideโ the functionโs scope.
Next, click on
Show in CodeLens and step through the code with the
Next
> button to follow the
flow of execution. CodeLens indicates the scope of the variables with โFrameโ boxes. Variables whose scope is
local to the function will be placed in a named box, and
global variables (defined outside of the function) will stay in the global frame.
Go through the steps until you see an error message. When we try to access
y
on line 6 (outside the functionโs scope), Python looks for a global variable named
y
but does not find one. This results in the runtime error:
NameError: name 'y' is not defined.
This is neither a syntax nor a semantic error - line 6 is syntactically correct and the algorithm is valid however...
The local variable
y
only exists while the function is being executed โ we call this its
lifetime. When the execution of the function terminates (returns), the local variables are destroyed and the code passes outside of the functionโs scope. CodeLens helps you visualize this because the functionโs local variables disappear after the function returns to the function callerโs scope (line 5).
Go back and step through the statements again, paying particular attention to the variables that are created when the function is called and note when they are subsequently destroyed with the functionโs return.
Use
Edit this code
to delete line 6
print(y)
and take a moment to work out for yourself what will now happen. Then
Visualize Execution
and proceed through all the steps. Answer for yourself
what happened? Why?
By tracing the algorithm (the
flow of execution) and watching the CodeLens frames (scope), you can see that formal parameters are local variables; their scope is limited to within their function. For example, after
square
is called, the local variable
x
exists with the functionโs body (lines 2 and 3). The lifetime of all local variables (including parameters) then ends when the function completes its execution and the scope passes back to the calling instruction (line 3โs
return
to line 6).
Try stepping through the code again. Look for, understand and fix any other runtime errors.
Checkpoint 4.8.3.
True or False: Local variables can be referenced outside of the function they were defined in.
Checkpoint 4.8.4.
What would be the result of running the following code?
x = 3 * 2
y = 1
def subtract(z):
y = 10
return y - z
print(subtract(x))
Correct, the output is right because the subtract function takes in x as the global variable for the z parameter and puts it into the function. The subtract function uses the local variable y for its return.
Incorrect, look again at what is being produced in the subtract function.
Incorrect, look again at what is being produced in the subtract function.
Code will give an error because x and z do not match.
Incorrect, there shouldnโt be any error.
Checkpoint 4.8.5.
What would be the result of running the following code?
def adding(x):
y = 3
z = y + x + x
return z
def producing(x):
z = x * y
return z
print(producing(adding(4)))
Incorrect, look again at what is happening in producing.
Incorrect, look again at what is happening in producing.
There is an error in the code.
Yes! There is an error because we reference y in the producing function, but it was defined in adding. Because y is a local variable, we canโt use it in both functions without initializing it in both. If we initialized y as 3 in both though, the answer would be 33.
Checkpoint 4.8.6.
What would be the result of running the following code?
x = 9
def adding():
x+=1
print(x)
adding()
Incorrect, pay attention to the local scope in the function.
Incorrect, pay attention to the local scope in the function.
Incorrect, pay attention to the local scope in the function.
Error, local variable โxโ is referenced before assignment.
This code gives an error because the local variable โxโ was referenced in the local scope before it was assigned a value.
In the code below, notice and interpret the different error messages produced when each is run.
-
NameError: Local variables cannot be used (add one to โexisting valueโ) if it does not yet have a value.
In a similar way, a function is not defined before its function header.
-
Local variables used within functions exist within the scope of that function, but they are considered
unbound if they donโt have a valid assignment statement.
v1 += 1
NameError: name 'v1' is not defined
foo()
def foo():
v1 += 1
NameError: name 'foo' is not defined
def foo():
v1 += 1
foo()
UnboundLocalError: local variable 'v1' referenced before assignment
Take a moment to work out how to โfixโ these runtime errors.
You have attempted
of
activities on this page.