LEGB Scoping Rule
Python resolves names in this order: Local → Enclosing → Global → Built-in (LEGB).
LEGB = Look Everywhere for Groceries, Buddy. You check your pocket (Local), your friend's bag (Enclosing), the car trunk (Global), then the store itself (Built-in). Always closest pocket first.
Local: inside the current function. Enclosing: in an enclosing function (for closures). Global: module-level. Built-in: Python's built-in namespace (len, print, etc.). The global keyword lets you write to global scope from inside a function. The nonlocal keyword lets you write to an enclosing scope.
Python determines at compile time whether a variable is local or global — if a name is assigned anywhere in a function, it's treated as local throughout that function (even before the assignment). This causes the UnboundLocalError trap. Each module has its own global scope — there is no single 'global' across modules. Class scope is NOT part of LEGB — comprehensions inside classes can't access class-scope variables directly.
Python resolves names using LEGB — Local, Enclosing, Global, Built-in. Each function call creates a new local scope. For closures, the enclosing scope is captured. Use 'global x' to write to module scope, 'nonlocal x' to write to an enclosing function's scope. Note: class bodies are NOT part of the LEGB chain — that catches people off guard with comprehensions inside classes.
If you assign to a variable anywhere in a function, Python treats it as local for the entire function — even above the assignment. Reading it before assignment gives UnboundLocalError, not the global value.