Python Scope of Variables
Table of Contents + β
In the last lesson you learned Lambda Functions, small one-line functions you write on the spot. Now we look at something that quietly affects every function you write. When you make a variable inside a function, where does it actually live? Can the rest of your program see it? This is called scope. Getting it clear will save you from a whole class of confusing bugs.
π€ Why Scope Matters
Picture a bigger program with many functions. One function uses a variable called total. Another function, written by someone else on your team, also uses a variable called total. If both total variables were shared across the whole program, they would step on each other. One function would change a value the other one was counting on. You would get wrong numbers and no clear reason why.
That is the pain scope solves. Scope is the part of your program where a variable can be seen and used. A variable made inside a function stays inside that function. So two functions can both use a name like total and never clash. Each one gets its own private copy.
π§© Local and Global
There are two kinds of scope you meet first.
- A local variable is made inside a function. It lives only inside that function. When the function finishes, it is gone.
- A global variable is made outside every function, at the top level of your file. It can be read from anywhere, including inside functions.
Think of it like rooms in a house. A local variable is a note left on a desk inside one room. Only the person in that room can read it. A global variable is a note stuck on the front door, where everyone in the house walks past and can read it.
π A Local Variable Stays Inside
Letβs see a local variable in action. This function makes a variable called message and prints it.
def greet(): message = "Hello from inside" print(message)
greet()The variable message is made inside greet. So it is local to greet. When we call the function, it prints fine.
Output
Hello from insideNow watch what happens if we try to use message outside the function. This is the part that surprises people.
def greet(): message = "Hello from inside" print(message)
greet()print(message) # trying to use it out herePython runs the function, prints the greeting, then crashes on the last line.
Output
Hello from insideTraceback (most recent call last): File "main.py", line 6, in <module> print(message) ^^^^^^^NameError: name 'message' is not definedRead that last line. NameError: name 'message' is not defined. Out here, message does not exist. It was born inside greet and it died when greet finished. That is exactly what local means. The variable simply is not visible outside its own function.
π Reading a Global Inside a Function
Now the other direction. A variable made outside any function is global. A function is allowed to look out and read it.
Here app_name is made at the top level, so it is global. The function reads it.
app_name = "Photo Editor"
def show_title(): print("Welcome to", app_name)
show_title()The function never made app_name itself. It just reached out and read the global one.
Output
Welcome to Photo EditorSo the rule is one-directional. A function can read a global variable. But a variable made inside a function cannot be seen from outside. Reading out is fine. Reaching in is not.
π How Python Looks Up a Name
When you use a variable inside a function, Python searches in a set order. It checks the closest place first, then moves outward.
- First it looks at the local names, the ones made inside this function.
- If it does not find the name there, it looks at the global names, the ones made at the top of the file.
- If it is still not found anywhere, you get that
NameError.
This is why a local total never clashes with another functionβs local total. Python finds the local one first and stops looking. Here is the short version of the two kinds.
| Scope | Where it is made | Who can see it |
|---|---|---|
| Local | Inside a function | Only that function |
| Global | At the top level of the file | The whole file, including inside functions |
βοΈ Changing a Global With the global Keyword
Reading a global is easy. But what if a function tries to change one? This trips people up. Letβs look.
count = 0
def add_one(): count = count + 1 # this line fails
add_one()You might expect count to become 1. Instead Python crashes.
Output
Traceback (most recent call last): File "main.py", line 6, in <module> add_one() File "main.py", line 4, in add_one count = count + 1 ^^^^^UnboundLocalError: cannot access local variable 'count' where it is not associated with a valueHere is what happened. The moment a function assigns to a name, Python treats that name as local to the function. So inside add_one, the count on the left is a brand new local variable. But the count on the right has no value yet. So Python complains.
If you really need the function to change the global one, you tell Python with the global keyword. It says βdo not make a new local, use the global oneβ.
count = 0
def add_one(): global count count = count + 1
add_one()add_one()print(count)The line global count tells the function to work on the global count, not a new local copy. Now each call really updates it.
Output
2It works. But read the warning below, because you will rarely want to do this.
Caution
Changing globals from inside functions is usually a sign of trouble. When many functions all reach in and edit the same global, you lose track of who changed what, and bugs get hard to find. The cleaner habit is to pass values in as arguments and return the result back out. Reach for global only when you have a strong, specific reason.
π§βπ» The Clean Way Instead
Here is the same counting idea written the recommended way. No global anywhere. The function takes a value in and hands a new value back.
def add_one(value): return value + 1
count = 0count = add_one(count)count = add_one(count)print(count)Walk through it.
add_onetakesvalueas an argument, so it works on whatever you pass in.- It returns
value + 1, a fresh result, without touching anything outside. - Out at the top level, we update
countourselves by catching what the function returned.
Output
2Same answer, 2. But now the function does not secretly change anything. You can read the code and see exactly where count gets updated. That clarity is why this style is preferred.
β οΈ Common Mistakes
A few scope traps catch people again and again. Watch for these.
- Trying to use a local variable outside its function. It does not exist out there, so you get a
NameError.
# β Avoid: result is local to calc, invisible outsidedef calc(): result = 5 * 5calc()print(result) # NameError
# β
Good: return it, then use it outsidedef calc(): return 5 * 5answer = calc()print(answer)- Assigning to a global inside a function without
global, then being surprised byUnboundLocalError. The moment you assign, Python makes it local. - Reaching for
globalas a quick fix. It often hides the real design problem. Pass values in and return them out instead.
# β Avoid: function quietly edits a globaltotal = 0def add(x): global total total = total + x
# β
Good: function returns, caller updatesdef add(total, x): return total + xtotal = 0total = add(total, 5)β Best Practices
Keep these habits and scope stays simple.
- Keep variables local by default. Make them inside the function that uses them.
- Pass data into a function with arguments, and send results back with
return. This keeps each function self-contained. - Treat global variables mostly as read-only settings, like an app name or a fixed limit.
- Avoid the
globalkeyword unless you have a clear, specific reason. There is almost always a cleaner way. - If two functions need to share and update the same value, return it and pass it along, rather than reaching into a global.
π§© What Youβve Learned
β Scope is the part of your program where a variable can be seen and used.
β
A local variable is made inside a function and exists only there. Using it outside gives a NameError.
β A global variable is made at the top level and can be read from inside functions.
β
Python looks for a name locally first, then globally, and raises a NameError if it finds it nowhere.
β
The global keyword lets a function change a global, but passing values in and returning them out is the cleaner habit.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
Where can a local variable be used?
Why: A local variable is created inside a function and lives only there. Outside that function it does not exist.
- 2
What happens if you print a local variable from outside its function?
Why: The variable does not exist outside its function, so Python cannot find the name and raises a NameError.
- 3
Can a function read a global variable that was made at the top of the file?
Why: Reading is allowed. A function can look outward and read a global variable without any special keyword.
- 4
What does the global keyword do inside a function?
Why: Without global, assigning a name makes it local. The global keyword tells Python to use and change the global variable instead.
π Whatβs Next?
You now know where your variables live and why keeping them local keeps your code clean. Next we look at a function that calls itself to solve a problem one small piece at a time.