Historical Context & Motivation
In the earliest days of programming, every variable in a program was accessible from everywhere in the code. This might sound convenient at first, but imagine a huge program with thousands of lines — any part of the code could accidentally change a variable that another part depended on. These sneaky bugs were incredibly hard to track down. As programming languages evolved, language designers introduced the idea of scope, a set of rules that determines where a variable can be seen and used. Scope became one of the most important concepts in software engineering because it keeps different parts of a program from stepping on each other's toes.
The central question that scope answers is straightforward: When I use a variable name, which variable am I actually referring to? Without clear scoping rules, two functions that both use a variable called count could silently overwrite each other's data. Understanding local and global scope in Python lets you write functions that are self-contained, predictable, and safe to reuse.
Core Principles & Definitions
Before diving into code, you need to understand four foundational ideas that govern how Python decides which variable you mean when you write a name like x or total. These principles will guide every function you write.
Scope
Local Scope
Global Scope
global keyword.Name Resolution (LEGB Rule)
Visual Explanation — Scope in Action
The diagram below illustrates how Python separates global scope from local scope. Notice that each function creates its own isolated box. Variables inside those boxes cannot leak out, and the global area sits around the outside.
Notice how the two function boxes are completely separate from each other. The variable result inside add() has no relationship to anything in greet(). Even if both functions happened to use a variable called x, each would have its own independent copy. This isolation is exactly what makes functions reliable and reusable.
How Python Resolves Variable Names — The LEGB Rule
When Python encounters a variable name — say x — it does not simply look everywhere at once. Instead, it follows a strict search order known as the LEGB rule. Python checks four layers, stopping as soon as it finds a match.
print, len, range.For this course, you will mostly deal with the Local and Global layers. The Enclosing layer matters when you write functions inside other functions, which is a more advanced topic. The Built-in layer is why you can use print() without importing anything — Python knows about it automatically.
The Assignment Rule
There is one critical rule that trips up beginners: if you assign to a variable anywhere inside a function, Python treats that variable as local to the entire function. This means even if a global variable with the same name exists, the function will create its own separate local copy. If you try to read the variable before the assignment line inside the function, you will get an UnboundLocalError because Python already decided the name is local, but it has not been assigned yet.
count = count + 1 inside a function when count is a global variable will crash with UnboundLocalError. The assignment makes Python treat count as local, but the right side tries to read it before the local version has a value.The global Keyword and Unintended Side Effects
Python provides the global keyword to let a function modify a global variable instead of creating a local one. You place global variable_name at the top of the function body before using that variable. While this works, experienced programmers use it very sparingly because it introduces side effects — the function reaches outside its own scope and changes something in the wider program. This makes the code harder to debug and test.
global that modifies the global variable directly, creating a side effect.Best Practice: Pass and Return Instead
The preferred approach is to pass global data into a function as a parameter and get the answer back with a return statement. This way, the function doesn't secretly reach outside itself. For example, instead of using global score inside the function, you can write def add_bonus(current_score): return current_score + 20 and then call score = add_bonus(score) in the main program. The result is the same, but now the data flow is visible and explicit.
Worked Example — Tracing Scope Step by Step
Let's trace through a short Python program and identify every variable's scope. Read the code below carefully, then follow each step.
color = "blue"
def paint_room(size):
color = "red"
area = size * size
return area
result = paint_room(10)
print(color)
print(result)color = "blue" is assigned at the top level, outside any function, so it lives in global scope. The variable result is also assigned at the top level, so it is global too.color, resultpaint_room, the parameter size is automatically local. The assignment color = "red" creates a brand-new local variable called color — it does NOT change the global color. The variable area is also assigned inside the function, so it is local.size, color, areapaint_room(10) is called, Python creates a local scope for the function. size gets the value 10. color is set to "red" locally. area becomes 10 × 10 = 100. The function returns 100.100paint_room is destroyed. The local color ("red"), size, and area no longer exist. The global color is still "blue" because the function never touched it.print(color) outputs blue — print(result) outputs 100color survived the function call unchanged because the assignment inside paint_room() created a completely separate local variable. This is Python's default safety mechanism: assignments inside functions stay local unless you explicitly say otherwise with global.Local vs. Global — Strengths and Limitations
Neither local nor global variables are inherently "bad," but they serve very different purposes. Understanding their strengths and limitations helps you make smart choices about where to store data in your programs.
| Feature | Local Variables | Global Variables |
|---|---|---|
| Lifetime | Created when the function is called; destroyed when it returns. | Exist from assignment until the program ends. |
| Visibility | Only visible inside the function where they are created. | Readable from anywhere; modifiable only with the global keyword. |
| Safety | Very safe — cannot be accidentally changed by other functions. | Risky — any function using global can change the value unexpectedly. |
| Debugging | Easy to trace because you only need to look inside one function. | Hard to trace because many functions could be modifying the value. |
| Best Use | Temporary calculations, loop counters, intermediate results. | Constants (values that never change), configuration settings. |
PI = 3.14159 or MAX_LIVES = 3. If you find yourself reaching for the global keyword frequently, it is a signal to redesign your functions to use parameters and return values instead.Connection to Advanced Concepts
The scoping concepts you've learned here form the foundation for several advanced programming topics. As you continue in computer science, you'll see these ideas expand and become even more powerful.
| What You Know Now | Where It Leads |
|---|---|
| Local variables belong to a single function | Closures — nested functions that "remember" local variables from their enclosing function even after it returns. |
| Avoiding global variables through parameters and return values | Object-Oriented Programming — classes bundle data (attributes) and functions (methods) together, giving data a clear "home" without using globals. |
| The LEGB name resolution rule | Namespaces and modules — Python uses namespaces to organize names across different files and libraries, extending the same idea of scoped lookup. |
| Functions as self-contained units | Pure functions and functional programming — functions that have no side effects and depend only on their inputs, making programs easier to test and reason about. |
You don't need to master these advanced topics right now, but knowing they exist helps you see the bigger picture. Every time you practice keeping your variables local, you are building habits that will serve you in AP Computer Science, college-level courses, and professional software development.
Practice Problems
x = 5
def double():
x = 10
return x * 2
result = double()
print(x)
print(result)global keyword.
total = 0
def add_to_total(value):
total = total + value
return total
add_to_total(5)earn_points(current_score, points) that returns the updated score after earning points, and lose_life(current_lives) that returns the number of lives after losing one. Neither function should use the global keyword. Show how you would call them from the main program.Lesson Summary
Scope determines where a variable can be accessed in your Python program. A local variable is created inside a function and exists only while that function runs — it is destroyed when the function returns. A global variable is created outside all functions and persists for the entire program. Python follows the LEGB rule (Local → Enclosing → Global → Built-in) to resolve variable names, always starting with the most local scope.
Assigning to a variable inside a function automatically makes it local, even if a global variable with the same name exists. To modify a global from inside a function, you must declare it with the global keyword — but this is generally discouraged because it creates side effects that make bugs harder to find. The best practice is to pass data through parameters and return values, keeping your functions self-contained, predictable, and easy to reuse.