Similar to how nested functions form a unique namespace within their enclosing functions (the enclosing namespace), there also exist special rules that apply for accessing nested values. These rules make up the enclosing scope (also known as nonlocal scope). Let’s take a look at a nested function to see the scope in action:
def outer_function(): enclosing_value = 'Enclosing Value' def nested_function(): nested_value = 'Nested Value' print(enclosing_value) nested_function() outer_function()
Our output would be:
Enclosing scope allows any value defined in an enclosing function to be accessed in nested functions below it. We can observe this scope since
nested_function() can access a variable defined one level above in the enclosing function (
We can also observe this scoping rule further if we nested a function one level deeper:
def outer_function(): enclosing_value = 'Enclosing Value' def nested_function(): nested_value = 'Nested Value' def second_nested(): print(enclosing_value) print(nested_value) second_nested() nested_function() outer_function()
Enclosing Value Nested Value
There are two caveats to be aware of with enclosing scope:
The flow of scope access only flows upwards. This means that the deepest level has access to every enclosing namespace above it, but not the other way around. For example, if we tried to access
nested_valuefrom one level above where it was defined:def outer_function(): enclosing_value = 'Enclosing Value' print(nested_value) def nested_function(): nested_value = 'Nested Value' nested_function() outer_function()
The program would produce an error:NameError: name 'nested_value' is not defined
Immutable objects, such as strings or numbers, can be accessed in nested functions, but cannot be modified. Let’s try to change
enclosing_valueto see this restriction in action:def outer_function(): enclosing_value = 'Enclosing Value' def nested_function(): enclosing_value += 'changed' nested_function() print(enclosing_value) outer_function()
UnboundLocalError: local variable 'enclosing_value' referenced before assignment
Let’s now practice accessing values in the enclosing scope!
A new addition to our painting application that we are building for Jiho will be a function that calculates the amount of paint needed to cover a surface.
Typically, a gallon of paint can cover about 400 square feet. Using that knowledge, we can use the width and height of a surface to determine how much paint is needed!
Throughout these exercises we will use nested functions to add more utility to the
calc_paint_amount() function. Remember, this now makes
calc_paint_amount() an enclosing function.
Run the code to move to the next exercise.
First inside of
- Define a nested function called
calc_gallons()that has no parameters.
Then inside of
calc_gallons(), use enclosing scope to access the variable
square_feet from the
- Return the result of
square_feetdivided by 400.
Finally, in the
calc_paint_amount() function, call the
calc_gallons() function and return the result.
Run the code and take a look at the result!