nonlocalAdvanced Examples

Declares a variable inside a nested function as belonging to the enclosing scope

nonlocal in decorators

Using nonlocal for stateful decorators.

python
import functools

def retry(max_attempts=3):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            attempts = 0
            last_error = None
            while attempts < max_attempts:
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    attempts += 1
                    last_error = e
                    print(f"  Attempt {attempts} failed: {e}")
            raise last_error
        return wrapper
    return decorator

call_count = 0

@retry(max_attempts=3)
def flaky_function():
    global call_count
    call_count += 1
    if call_count < 3:
        raise ConnectionError("Network down")
    return "Success!"

print(flaky_function())
Expected Output
  Attempt 1 failed: Network down
  Attempt 2 failed: Network down
Success!

Decorators naturally create closures. nonlocal is useful when a decorator needs to maintain state between calls (like counting retries or caching results).

Want to try these examples interactively?

Open Advanced Playground