Python nonlocal Keyword (original) (raw)

The **nonlocal keyword in Python is used within nested functions to indicate that a variable refers to a previously bound variable in the nearest enclosing but non-global scope. This allows modification of variables in an outer function from within an inner function without making them global.

**Example:

Python `

def outer(): message = "Hello"

def inner():
    nonlocal message  # Reference the enclosing variable
    message = "Hello, Python!"  # Modify it
    print("Inside inner:", message)

inner()
print("Inside outer:", message)

outer()

`

Output

Inside inner: Hello, Python! Inside outer: Hello, Python!

Explanation: Here, nonlocal message ensures that message inside inner() modifies the message variable from**outer() instead of creating a new local variable.

Why use nonlocal ?

In Python, variables have different scopes:

When a variable is declared inside a function, it is local by default. The nonlocal keyword allows modifying an enclosing function's variable instead of creating a new local variable.

nonlocal vs global

While both nonlocal and global allow modifying variables from an outer scope, their scope is different:

Keyword Scope affected can modify local variable ? can modify global variable ?
nonlocal Enclosing (non-global ) function scope Yes No
global global scope No Yes

**Example:

Python `

a = "I am global"

def outer(): b = "I am enclosing"

def inner():
    global a
    nonlocal b
    a = "Modified global"
    b = "Modified enclosing"

inner()
print("Inside outer:", b)

outer() print("Outside outer:", a)

`

Output

Inside outer: Modified enclosing Outside outer: Modified global

Explanation: Here,**a is modified globally using global, while**b** is modified in the enclosing scope using nonlocal.

Rules and Restrictions of non local

**Example: Incorrect usage

Python `

Global variable

global_a = 'geeksforgeeks'

def outer(): def inner(): nonlocal global_a # Attempting to reference global variable global_a = 'GeeksForGeeks' # Modifying the variable print(global_a) inner() outer()

`

**Output:

Hangup (SIGHUP)
File "/home/guest/sandbox/Solution.py", line 6
nonlocal global_a # Attempting to reference global variable
^^^^^^^^^^^^^^^^^
SyntaxError: no binding for nonlocal 'global_a' found

**Explanation: This will result in an error because nonlocal can only reference variables from an enclosing function, not from the global scope.

Scope resolution with nonlocal

When multiple nested functions have a variable with the same name, nonlocal references the nearest enclosing function’s variable, not the global one.

Python `

def fun1(): name = "geek"

def fun2():
    name = "Geek"
    
    def fun3():
        nonlocal name  
        name = 'GEEK'  # Modify before using
        print(name)  
    
    fun3()
    print(name)  # Modified value in fun2()

fun2()
print(name)  # Unchanged value in fun1()

fun1()

`

**Explanation: fun3() uses nonlocal to modify name in **fun2() to "GEEK", which both **fun3() and fun2() print. **fun1() remains unaffected, printing "geek", showing nonlocal affects only the nearest enclosing scope.

Practical application of nonlocal

One common use case of nonlocal is maintaining state in closures, such as implementing a counter function.

Python `

def counter(): count = 0 # Enclosed variable

def increment():
    nonlocal count  # Reference count from the outer function
    count += 1
    return count

return increment

Create a counter instance

counter1 = counter() print(counter1())
print(counter1())
print(counter1())

`

**Explanation: This code uses **nonlocal in a closure to maintain count across calls, allowing **increment() to update and return it.

Advantages of nonlocal

Disadvantages of nonlocal