Skip to main content

Foundations of Python Programming: Functions First

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).

Note 4.8.2.

When a function assigns and uses a local variable, upon completing its execution, it is not possible to recover that local variable the next time it is called. Each call of the function creates new local variables, and their lifetimes expire when the function returns to the caller’s scope.
Try stepping through the code again. Look for, understand and fix any other runtime errors.
Check Your Understanding

Checkpoint 4.8.3.

    True or False: Local variables can be referenced outside of the function they were defined in.
  • True
  • Local variables cannot be referenced outside of the function they were defined in.
  • False
  • Local variables cannot 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))
    
  • 4
  • 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.
  • 6
  • Incorrect, look again at what is being produced in the subtract function.
  • 10
  • 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)))
    
  • 33
  • Incorrect, look again at what is happening in producing.
  • 12
  • 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()
    
  • 1
  • Incorrect, pay attention to the local scope in the function.
  • 9
  • Incorrect, pay attention to the local scope in the function.
  • 10
  • 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.