nonlocal keyword is used inside a nested function to access and modify a variable from its enclosing function. It allows the inner function to update the outer function's variable without making it global.
def outer():
message = "Hello"
def inner():
nonlocal message
message = "Hello, Python!"
inner()
print(message)
outer()
Output
Hello, Python!
Explanation: statement nonlocal message refers to the message variable in the enclosing outer() function. After updating its value inside inner(), the modified value is printed by the outer function.
Nearest Enclosing Scope
When multiple nested functions contain variables with the same name, the nonlocal keyword refers to the variable in the nearest enclosing function.
def outer():
message = "Outer"
def middle():
message = "Middle"
def inner():
nonlocal message
message = "Updated"
inner()
print(message)
middle()
print(message)
outer()
Output
Updated Outer
Explanation: statement nonlocal message refers to the message variable in middle(), which is the nearest enclosing function. Therefore, only that variable is updated, while the message variable in outer() remains unchanged.
Maintaining State with Closures
The nonlocal keyword can be used to preserve and update values across multiple calls to a nested function.
def counter():
count = 0
def increment():
nonlocal count
count += 1
return count
return increment
counter1 = counter()
print(counter1())
print(counter1())
print(counter1())
Output
1 2 3
Explanation: variable count belongs to the outer counter() function. The statement nonlocal count allows increment() to update its value, so the counter remembers the previous count each time it is called.
Limitations of nonlocal
The nonlocal keyword can only be used to access variables from an enclosing function. It cannot be used to access global variables.
message = "Hello"
def outer():
def inner():
nonlocal message
message = "Hi"
inner()
outer()
Output
ERROR!
Traceback (most recent call last):
File "<main.py>", line 5
SyntaxError: no binding for nonlocal 'message' found
Explanation: variable message is defined in the global scope, not in an enclosing function. Since nonlocal works only with variables from an enclosing function, Python raises a SyntaxError.
nonlocal vs global
Both nonlocal and global allow a function to modify a variable defined outside its local scope. However, they refer to variables in different scopes.
| Keyword | Scope Affected | Can Modify an Enclosing Variable? | Can Modify a Global Variable? |
|---|---|---|---|
| nonlocal | Enclosing function | Yes | No |
| global | Global scope | No | Yes |
Examples: Here, we use both global and nonlocal to modify variables from different scopes.
message = "Global"
def outer():
text = "Outer"
def inner():
global message
nonlocal text
message = "Updated Global"
text = "Updated Outer"
inner()
print(text)
outer()
print(message)
Output
Updated Outer Updated Global
Explanation: statement nonlocal text modifies the variable text from the enclosing outer() function. The statement global message modifies the global variable message. As a result, both updated values are reflected in their respective scopes.