Python Programming · Foundations
Scope
On this page 9 sections
In 30 seconds
scope The region of code in which a name can be accessed directly. Full entry → is the part of a Python program where a name can be found directly. When code uses an unqualified name, Python checks the current function's local names first, then names in enclosing functions, then the module's global names, and finally built-in names. This familiar sequence is often called LEGB. Assignment changes the picture: an assignment in a function normally creates or rebinds a local name unless global or nonlocal says otherwise.
Why this matters
Scope lets a reader predict which value a name means without guessing. It explains why a helper can read a module-level setting, why a nested function can remember surrounding state, and why a seemingly harmless count = count + 1 can fail. In coursework, scope is essential for tracing code and diagnosing name errors. In larger programs, deliberately choosing local, enclosing, or module-level state helps limit unintended interactions and makes changes safer to reason about.
The college version
Scope is about name visibility
A Python name is a label that code uses to reach a value. Scope answers a narrower question than what value this is: where may the program look for that label without qualifying it? For an ordinary name used inside a function, the search begins in the local scope The names associated with one function call. Full entry → created for that call. If the name is absent there, Python can search the scopes of enclosing functions, beginning with the nearest. Next comes the global scope The namespace at the top level of the module that defines a function. Full entry → of the module that defined the function. Finally, Python can use the built-in namespace The namespace that supplies standard names such as len. Full entry →, where names such as len live. LEGB is a convenient mnemonic for this local–enclosing–global–built-in order. The order matters only until a matching binding Associating a name with a value in a namespace. Full entry → is found. If an inner function has a local label, that binding hides an enclosing or global label of the same spelling for uses inside the inner function. Outside that function, the local binding is not directly available. A scope rule is therefore a predictable lookup rule, not a claim that only one name with a particular spelling may exist in a program.
Reading differs from rebinding
Code inside a function may read an outer name when it does not bind that name locally. Assignment is the crucial event. If Python finds a name-binding operation anywhere in a function block, uses of that name in that block are treated as local by default. This is a whole-block rule, not a line-by-line discovery rule. That rule explains a common surprise. Suppose module code binds count = 10, then a function contains count = count + 1. The assignment means count is local in that function, so the expression on the right tries to read that local count before it has a value. Python raises UnboundLocalError; it does not fall back to the module value. The language reference identifies this as a special case of NameError. The repair is not to rely on a mysterious exception: decide whether the function should instead receive and return a value, maintain enclosing state, or intentionally rebind Make a name refer to a different value in its selected scope. Full entry → a module name. This lesson focuses on the lookup consequence, while function interfaces belong in the adjacent lessons.
global and nonlocal are explicit rebinding choices
global name inside a function tells Python that references and assignments to name in that block use the module-level global namespace. It is not a general instruction to search outside; it specifically selects the defining module's global namespace. Because it changes how the block is compiled, it must appear before uses of that name in the block. Global state can be appropriate for narrowly scoped configuration or a deliberate shared counter, but its effects can be harder to trace than local state. nonlocal name is for a nested function that needs to rebind a name from an enclosing function. It does not target a module global, and it cannot create a brand-new enclosing binding. The named value must already be bound in an enclosing function scope; otherwise Python reports SyntaxError while compiling the code. This is useful for a closure A nested function that retains access to names from an enclosing function. Full entry →: an inner function can keep access to a surrounding function's state after the outer call has produced it. Use nonlocal only when that persistent enclosing state is intentional.
Trace one lookup at a time
When tracing scope, first mark every assignment in each function block. Then, for the name being read, ask: is it local here? If not, is there an enclosing function binding? Then check the module global and built-ins. For a rebind, look for global or nonlocal before assuming an outer value changes. This mechanical method avoids two frequent errors: treating any outer name as automatically writable, and assuming that a global name saves a local variable that has not yet been bound. Write the lookup path beside each reference before predicting output; doing so turns an intuition problem into a checkable trace.

Eli explains
The same idea, in plain words
Explain it like I’m 10
Imagine each function call is a desk with labeled drawers. To find a note called label, first open the drawer on the desk in front of you. If it is not there, look at desks belonging to functions wrapped around yours, then at the big desk for the whole file, and finally at the shared supply cabinet of built-in names. That is the lookup part of scope. Writing a new note changes the rule. If you write label = "local" at your desk, Python treats label as a label for your desk in that function. It does not silently replace a note at the big file desk. global explicitly says to write at the file desk. nonlocal says to write at the nearest surrounding function’s desk; that desk must already have the note.
Picture it like this
Scope is like looking for a labeled note through your desk, surrounding desks, the file desk, and then a shared supply cabinet.
Where the picture stops working
The desks do not describe physical storage, object mutation, or module imports; they only model name lookup and rebinding choices.
Worked example
This executed example has a module-level message and an enclosing message. outer creates the enclosing binding. Its nested inner uses nonlocal message, so its assignment changes outer's binding rather than creating an inner local. The module-level value remains untouched. A separate function, add_one_bad, contains an assignment to count; therefore count is local for that entire function. Its read occurs before that local binding, so the run raises UnboundLocalError.
message = "outer"
def outer():
message = "enclosing"
def inner():
nonlocal message
message = "changed enclosing"
inner()
return message
print(outer(), message) # changed enclosing outer
count = 10
def add_one_bad():
count = count + 1
try:
add_one_bad()
except UnboundLocalError as error:
print(type(error).__name__) # UnboundLocalErrorKey takeaway
Use LEGB to predict where a Python name is read. Then treat assignment as a separate decision: it is local by default, global targets the module namespace, and nonlocal targets an existing enclosing-function binding.
Quick check
3 questions here, of 5 in this lesson’s practice set. Answers stay hidden until you check.
A function contains total = total + 1 and no global or nonlocal statement. Why can its first call raise UnboundLocalError?
In a nested function, what does nonlocal score require?
Study tools & related lessonsYou’ll learn to · Common mistakes · Easily confused · Key vocabulary · Related
You’ll learn to
- Define scope and describe the LEGB lookup order.
- Distinguish reading an outer name from rebinding a name locally.
- Explain when
globalandnonlocalchange assignment behavior. - Diagnose an
UnboundLocalErrorcaused by a local binding. - Apply name-resolution rules to a nested-function example.
Common mistakes
Assuming Python always reads a same-named global before a local.
Mark assignments first; one in the function normally makes the name local throughout that block.
Using
globalmerely to read a global value.Reading can use the normal lookup path; reserve
globalfor deliberate global rebinding.Using
nonlocalfor a module variable.nonlocalrequires a previously bound name in an enclosing function; useglobalonly when module rebinding is truly intended.Treating
UnboundLocalErroras a missing-name error only.Check whether a later assignment caused Python to classify the name as local.
Easily confused
`global x` vs. `nonlocal x`
global selects the module namespace; nonlocal selects a previously bound enclosing-function name.
Reading an outer name vs. Rebinding a name
A read can follow normal lookup; assignment normally creates a local binding unless declared otherwise.
`NameError` vs. `UnboundLocalError`
A missing name raises NameError; using a function-local name before it is bound raises the more specific UnboundLocalError.
Key vocabulary
- scope
- The region of code in which a name can be accessed directly.
- local scope
- The names associated with one function call.
- enclosing scope
- A surrounding function's scope visible to a nested function.
- global scope
- The namespace at the top level of the module that defines a function.
- built-in namespace
- The namespace that supplies standard names such as
len. - binding
- Associating a name with a value in a namespace.
- rebind
- Make a name refer to a different value in its selected scope.
- closure
- A nested function that retains access to names from an enclosing function.
- UnboundLocalError
- The error raised when a function tries to use its local name before that name has been bound.
Sources & references
- The Python Tutorial — 9.2 Python Scopes and Namespaces — Python Software Foundation
- The Python Language Reference — Execution model (naming and binding) — Python Software Foundation
EliExplains lessons are original prose written from the open, credible references above. See Copyright & Licensing.
Researched 2026-08-19
Educational content only. It is not medical, legal or professional advice. Found an error? Tell us.

