Python — Scope
LEGB — the lookup order
Python resolves a name by searching four scopes in order:
L — Local inside the current function
E — Enclosing the function wrapping this one
G — Global module top-level
B — Built-in print, len, sum…
x = "global"
def outer():
x = "enclosing"
def inner():
x = "local"
print(x) # local wins — nearest scope first
inner()
outer()
Reading works across; writing stays local
Assigning inside a function creates a LOCAL variable, even if a global exists:
count = 0
def bump():
count = 99 # creates a NEW local — global untouched!
bump()
print(count) # 0
Reading is fine without declaration:
def show():
print(count) # sees the global 0 ✓
global — actually writing to it
count = 0
def bump():
global count
count += 1 # now modifies the module-level variable
bump()
print(count) # 1
Use sparingly — hidden mutations through globals are a classic bug source. Returning values instead keeps functions testable.
nonlocal — writing to ENCLOSING scope
For nested functions (closures):
def make_counter():
count = 0
def increment():
nonlocal count # targets make_counter's count
count += 1
return count
return increment
c = make_counter()
c(); c() # 1, 2 — state persists in the closure
| Keyword | Targets |
|---|---|
| (nothing) | reads fall through LEGB |
global x | module-level x |
nonlocal x | nearest ENCLOSING function's x |
Closures remember their birth scope
The counter above proves functions carry their defining environment. Loop gotcha with late binding:
funcs = [lambda: i for i in range(3)]
[f() for f in funcs] # [2, 2, 2] — all share the final i!
funcs = [lambda i=i: i for i in range(3)] # default freezes value now
[f() for f in funcs] # [0, 1, 2]
Block scope does NOT exist in Python
Unlike JS/Java, if/for/while blocks create NO new scope:
for i in range(3):
pass
print(i) # 2 — still alive! (JS would error with let)
Only functions/classes introduce new scopes.
Gotchas: built-in shadowing (
list = [1,2]breakslist()afterward!) · mutable globals mutated WITHOUT global keyword are fine (items.appendmutates, doesn't rebind).
Mini Practice
- Three-level nesting; predict which x prints from each level.
- Demonstrate read-works/write-local behavior.
- Fix a broken counter using nonlocal.
- Late-binding loop bug; fix via default argument.
- Shadow built-in str; then repair your script's lesson.
Next: modules →
Related Topics
Frequently Asked Questions about Scope
What is Scope in Python?
Scope is a fundamental concept in Python. This lesson explains it step by step with clear examples, making it easy for beginners to understand.
How do I learn Scope?
Start by reading the explanation above, then try the code examples. Practice by modifying the examples and experimenting with different values. Hands-on practice is the best way to learn Scope.
Why is Scope important in Python?
Scope is essential for Python development. Understanding this concept will help you write better code and solve real-world problems more effectively.