Scopes and Name Resolution

Local scope - inside a function

Enclosing scope - from outer function if nested

Global - Top leve script

def serve_chai():
    chai_type = "Masala" # local scope
    print(f"Inside function {chai_type}")
chai_type = "Lemon"
serve_chai()
print(f"Outside function: {chai_type}")


def chai_counter():
    chai_order = "lemon" # Enclosing scope
    def print_order():
        chai_order = "Ginger"
        print("Inner:", chai_order)
    print_order()
    print("Outer: ", chai_order)
chai_order = "Tulsi" # Global
chai_counter()
print("Global :", chai_order)

NonLocal - The nonlocal keyword is used to modify a variable in an enclosing but non-global scope, which is specifically relevant for nested functions.

chai_type = "ginger"
def update_order():
    chai_type = "Elaichi" # This is the "nonlocal" scope
    def kitchen():
        nonlocal chai_type
        chai_type = "Kesar"  # This modifies the 'chai_type' in outer_function
    kitchen()
    print("After kitchen update", chai_type)

update_order()

Global - The global keyword is used to modify a variable in the global scope.

chai_type = "Plain" # This is in the global scope

def front_desk():
    def kitchen():
        global chai_type
        chai_type = "Irnai" # This modifies the global 'chai_type'
    kitchen()

front_desk()
print("Final global chai: ", chai_type)