Python nested functions variable scoping
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
Nested functions in Python are straightforward when the inner function only reads values from the outer scope. Confusion starts when the inner function tries to assign to those names, because assignment changes how Python resolves scope. The fix is to understand the LEGB lookup rule and to use nonlocal or global only when you truly mean to rebind a name outside the current function.
The LEGB Rule
Python resolves names in this order:
- Local
- Enclosing
- Global
- Built-in
That means an inner function can read variables from its enclosing function, but writing to them is different. If you assign to a name inside a function, Python treats that name as local to that function unless you declare otherwise.
Reading an Outer Variable
Reading works naturally:
inner can access message because it lives in the enclosing scope.
Why Assignment Causes Problems
This version fails:
Python raises UnboundLocalError. The reason is not that count is invisible. The problem is that count += 1 counts as assignment, so Python marks count as local to inner, then notices it is being read before that local value exists.
Use nonlocal for Enclosing Function Variables
If the inner function should modify the variable from the enclosing function, declare it nonlocal:
Now both calls update the same count stored in the enclosing scope.
Use nonlocal only for names defined in an enclosing function. It does not refer to module-level globals.
Use global for Module-Level Names
If the name lives at module scope and you want to rebind it, use global:
This works, but global state is usually harder to test and reason about than enclosed state.
Closures and Remembered State
Nested functions become especially useful when you return the inner function and let it keep access to the outer variables. That is called a closure.
The returned function remembers count even after make_counter has finished.
A Common Late-Binding Surprise
Another scoping issue appears when nested functions are created in a loop:
This prints 2, 2, 2, not 0, 1, 2. Each function looks up i when it is called, not when it is defined.
One common fix is to bind the current value as a default argument:
Now the result is 0, 1, 2.
When to Prefer Another Design
If nested functions start carrying a large amount of mutable state, a small class or dataclass may be clearer. Closures are excellent for compact stateful helpers, but they are not always the best long-term shape for complicated logic.
Common Pitfalls
- Assuming reading and writing outer variables follow the same scoping rule.
- Forgetting that assignment makes a name local unless
nonlocalorglobalis declared. - Using
globalwhen the correct target is an enclosing function variable. - Hitting late binding in loops and thinking closures copied the loop variable automatically.
- Building complex mutable state in closures when a small object would be clearer.
Summary
- Python resolves names with the LEGB rule.
- Inner functions can read enclosing variables directly.
- To rebind an enclosing function variable, use
nonlocal. - To rebind a module-level variable, use
global. - Closures are useful, but assignment and late binding are the two main sources of confusion.
Related reading
- Python Neural Network - TypeError 'History' object is not subscriptable
- Python NLP Intent Identification
- Python NLTK pos_tag not returning the correct part-of-speech tag
- Python non-greedy regexes
- Python Non negative Matrix Factorization that handles both zeros and missing data?
- Python None comparison should I use is or ?
- Python not working in the command line of git bash
- Python not working in the command line of git bash
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.