In Python, you mainly deal with variables that are either:
- Global variables (declared outside of the function’s body, that is, in the global scope)
- Local variables (declared inside a function, that is, in the local scope)
But when you have a function inside another function, the outer function’s variables are neither local nor global in the eyes of the inner function. These variables are called nonlocal variables in Python.
If you need to work with a nonlocal variable in Python, you need to use the nonlocal keyword. In other words, if you need to access the outer function’s variable from the inner function, you need to use the nonlocal keyword.
This guide teaches you how the nonlocal keyword works with useful examples.
Before moving to the nonlocal keyword, it might be worthwhile checking a quick recap of Python scopes.
Scopes in Python
- A variable that lives inside a function belongs to the function’s local scope. No other parts of the code can access the variable except for what’s inside the function.
- A function inside a function has its own local scope, but also the enclosing scope by the outer function. This is known as the nonlocal scope.
- The global scope is the “default” scope in Python. Everything that lives outside a function belongs to the global scope.
- The built-in scope is the broadest scope that there is. It even governs the global scope. The built-in scope is accessible everywhere. For example, all Python keywords live in the built-in scope and can be used in any part of your code.
Nested Functions in Python
In Python, you can have a function that lives inside a function. This is called a nested function.
When working with nested functions, it’s important to realize how the scoping changes.
With a traditional function, everything that’s inside the function belongs to the local scope. And everything outside belongs to the global scope.
But when there’s a function inside a function, the inner function sees its local scope, the outer function’s enclosing scope (nonlocal scope), and the global scope.
Example 1. Simple Nested Function
def outer(): print("Outer function") def inner(): print("Inner function") inner() outer()
Outer function Inner function
This is an example of a nested function in which the inner() function is governed by an outer() function.
Generally, it can be useful to specify a nested function if you want to create a function that is not globally accessible. In the above example, calling the inner() function is not possible anywhere else in the code except inside the outer() function.
Both the outer() and inner() functions have access to global scopes, built-in scopes, and the functions’ local scopes. Besides, the inner() function has an access to the enclosing scope, that is, the outer() function’s scope.
In the eyes of the inner() function, the outer() function’s enclosing scope is neither global nor local. This is why Python calls the enclosing scope a nonlocal scope.
Example 2. Searching for Variables in Governing Scopes
To visualize the scoping of nested functions better, let’s modify the above example a bit:
def outer(): text = "Outer function" print(text) def inner(): print(text) inner() outer()
Outer function Outer function
Now, when the inner() function runs, Python doesn’t find the text variable in the local scope of the inner() function because it’s not defined there. Thus, Python checks the inner() function’s enclosing scope (the nonlocal scope) to see if the text variable is there. Because this is the case, Python prints the nonlocal text variable in the inner() function call.
The key takeaway here is if Python doesn’t find a variable in the current scope, it will search for it in the parent scope starting from the local scope all the way to the built-in scope.
The nonlocal Keyword
If you have a nested function that has a variable with the same name as the enclosing function and you want to access it, you need to use the nonlocal keyword.
By doing this, you let the Python interpreter know you are not referring to the variable in the local scope but the one in the enclosing function instead.
For example, here’s a nested function bar() that lives inside a function foo(). Both functions declare a variable called name. To access the name variable of the foo() function inside the bar() function, you need to use the nonlocal keyword:
def foo(): name = "Alice" def bar(): # Overwrite the name="Alice" variable nonlocal name name = "Bob" print(name) # Call the inner function bar() bar() # Print foo()'s local variable name print(name) foo()
So the nonlocal keyword tells Python you are referring to the enclosing function’s variables instead of the local ones.
Today you learned what is the nonlocal keyword in Python and how you can use it.
To take home, the nonlocal keyword references the variables in the parent scope. Using the nonlocal keyword is useful if you want to access the parent scope variable in a nested function.
Thanks for reading. Happy coding!