Phase: 4. Functions | Estimated time: 1.5 hours | Milestone Project: No
- Module 031 (Functions: Basics)
- Module 032 (Function Arguments)
By the end of this module, you will be able to:
- Explain the LEGB rule (Local, Enclosing, Global, Built-in)
- Use the
globalkeyword to modify global variables - Use the
nonlocalkeyword to modify enclosing scope variables - Visualize Python's namespace hierarchy
- Trace how Python looks up variable names
- Understand variable shadowing
Scope rules determine which variables your code can see. Misunderstanding scope leads to confusing bugs like "why doesn't my function see that variable?" or "why did my variable change globally?"
Python looks up variable names in this order:
L — Local (inside the current function)
E — Enclosing (any enclosing function, e.g., outer function)
G — Global (top-level of the module)
B — Built-in (Python's built-in names like print, len)
┌─────────────────────────────────────┐
│ Built-in │
│ print, len, range, int, ... │
│ ┌───────────────────────────────┐ │
│ │ Global │ │
│ │ x = 10, PI = 3.14 │ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ Enclosing (outer) │ │ │
│ │ │ y = 20 │ │ │
│ │ │ ┌───────────────────┐ │ │ │
│ │ │ │ Local (inner) │ │ │ │
│ │ │ │ z = 30 │ │ │ │
│ │ │ └───────────────────┘ │ │ │
│ │ └─────────────────────────┘ │ │
│ └───────────────────────────────┘ │
└─────────────────────────────────────┘
Lookup: inner → outer → global → built-in
Variables defined inside a function are local:
def my_func():
x = 5 # local — not accessible outside
print(x)Variables defined at the module top level are global:
y = 10 # global
def show_y():
print(y) # can read global
show_y() # 10To modify a global variable inside a function, use global:
counter = 0
def increment():
global counter
counter += 1
increment()
print(counter) # 1To modify a variable in an enclosing (outer) scope, use nonlocal:
def outer():
x = 10
def inner():
nonlocal x
x += 5
inner()
print(x) # 15When a local variable has the same name as a global one, it "shadows" it:
x = 100
def shadow():
x = 200 # shadows the global x
print(x) # 200
shadow()
print(x) # 100 — global unchanged- Trying to modify a global without
global: Creates a new local instead (or raises UnboundLocalError). - Forgetting
nonlocalin nested functions: Creates a new local instead of modifying the enclosing variable. - Accidental shadowing: A local variable hides a global one with the same name.
- Too many globals: Makes code hard to reason about — prefer passing parameters.
- Create a global variable
count = 0. - Write a function
increment()that usesglobalto add 1. - Write an outer function with an inner function that uses
nonlocal. - Experiment with shadowing — create a local variable with the same name as a global.
- LEGB: Local → Enclosing → Global → Built-in.
globallets you modify module-level variables inside a function.nonlocallets you modify enclosing function variables.- Shadowing is when a local name hides an outer name.
- Minimize global variables for cleaner code.
Continue to Module 034: Lambda Functions.