Function Scope and Local Variables
Use this test when analyzing a variable: Where was the name declared, and what block contains that declaration? Those answers identify the variable's scope according to the source's rule.
Try it: Scope: Local, Enclosing, Global, Built-in
How Python looks up a name Local → Enclosing → Global → Built-in, why assigning to a name inside a function makes it local (and raises UnboundLocalError if it is read first), and what global, nonlocal and closures change.
How it works
- Before a function runs, Python marks every name assigned inside it as local to that function, unless it is declared global or nonlocal.
- Reading a name searches the local namespace, then enclosing functions, then the module's globals, then the built-ins; the first hit wins.
- A local name read before it has a value raises UnboundLocalError (Python does not fall back to the global).
- global x makes assignments go to the module namespace; nonlocal x makes them go to the nearest enclosing function.
- A function's local frame disappears when it returns, unless an inner function (a closure) still uses its variables.
Default run (10 steps): Ready: Local shadows global. Every name is looked up Local, then Enclosing, then Global, then Built-in. … Finished. Printed: inside: 99 / outside: 10.
Simplified: The lab's own small Python interpreter runs a fixed, hand-written script (you choose the variant and the values, never the code); nothing is executed as real Python. Every script was run in CPython 3.12 with the same inputs and the lab reproduces its output and error messages. Built-ins shows only the names the script used.
Loading the simulation…
Two Places, One Name
Imagine that the surrounding program uses a variable named x, while a function also declares a variable named x. The matching spelling does not make these variables the same. A name declared inside a function is local to that function and is not related to another variable with the same name outside the function.
Following a Value Through a Function
The addtwo trace
Track the names and values when addtwo is called with 3 and 5, computes their sum in a local variable named added, and sends the result back to the calling code.
- 1Arguments enter the function
Within the function, the parameters a and b have the values 3 and 5 respectively.
- 2The local calculation occurs
The function computes the sum of a and b and places that sum in its local function variable named added.
- 3The result leaves the function
The return statement sends the computed value back to the calling code.
- 4The caller receives the result
The calling code assigns the returned value to x and then prints x.
The printed result is 8.
This trace separates two roles. The function uses its local names a, b, and added while doing its work. The calling code uses x after receiving the returned result. The function does not make its local variable added into the caller's variable x; instead, return communicates the computed value to the calling code, where that value is assigned to x.
What Scope Means
Scope is the part of a program in which a variable name belongs to its declaration. When a variable is declared inside a function definition, its name is local to that function. A same-named variable used outside the function is a separate variable, not another reference to the function's local name.
The source describes scope in terms of a block. Every variable has the scope of the block in which its name is declared, beginning at the point where that name is defined. For a function-local variable, the relevant block is the function. The name therefore belongs to the function's local context rather than automatically belonging to the surrounding program.
Where Availability Begins
Scope does not begin everywhere in the program merely because a name exists somewhere. The source states that a variable has the scope of its block starting from the point where the name is defined. This gives scope both a location and a starting point: identify the block, then identify where the declaration occurs within that block.
Use this test when analyzing a variable: Where was the name declared, and what block contains that declaration? Those answers identify the variable's scope according to the source's rule.
Changing a Top-Level Name
This rule is a direct consequence of keeping local and outside names distinct. A function's ordinary local name should not be treated as an assignment to a top-level name. The global statement is the explicit instruction that changes which name an assignment targets.
Mistakes Beginners Make
Common mistake Assuming that same spelling means same variable.
What it looks likeA function declares x, and the surrounding program also uses x.
Why it failsThe source states that a variable declared inside a function is not related to a same-named variable outside that function.
Do this insteadTreat the two names as belonging to separate scopes.
Common mistake Forgetting where scope begins.
What it looks likeTreating a variable as available throughout its block before the point where its name is defined.
Why it failsScope begins at the point of definition of the name.
Do this insteadLocate the declaration first, then trace the scope from that point through the block.
Common mistake Expecting a function's local calculation variable to appear automatically in the calling code.
What it looks likeExpecting the caller to use the function's local variable added directly.
Why it failsIn the source example, added is local to the function, while the calling code receives the value through return and assigns it to x.
Do this insteadFollow the returned value into the calling code instead of treating the local name as shared.
Common mistake Assigning to a top-level name inside a function without global.
What it looks likeTrying to assign a new value to a name defined at the top level without declaring it global.
Why it failsThe source states that assignment to a variable defined outside a function is impossible without the global statement.
Do this insteadUse the global statement when the intended target is the top-level name.
Scope Check Practice
A function receives two values, stores their sum in a local name, and returns the sum. The calling code stores the returned value in a different name. Identify which names belong to the function and which name belongs to the calling code. Then explain why the function's local sum name is not the same variable as the caller's result name.
Hints
- Start by listing the names declared or used inside the function.
- Separate the local calculation from the value returned to the caller.
- Use the rule that same-named variables in different scopes are not related.
What do you think happens?
Before reading the explanation, predict whether a function's local variable named added automatically becomes the caller's variable x.
Reveal answer
No, because the names belong to separate scopes.
In the source example, the function places the sum in local added, then return sends the value to the calling code, where it is assigned to x.
The Scope Checklist
- 1A variable declared inside a function is local to that function.
- 2A same-named variable outside the function is separate and unrelated to the local variable.
- 3A variable's scope is the block where its name is declared, beginning at the point of definition.
- 4A function can send a computed value to calling code with return; the caller can assign that value to its own variable.
- 5The global statement is required when a function is meant to assign to a name defined at the top level.
Key Takeaways
- Function scope keeps names declared inside a function local to that function.
- Matching names inside and outside a function still refer to separate variables.
- Scope begins where a name is defined and belongs to that name's block.
- Return passes a value to calling code without making the function's local variable shared.
- The global statement explicitly identifies a top-level name that a function is meant to assign.