Of course! This is a fundamental concept in Python that often trips up beginners. Let's break it down with clear explanations and examples.

The Core Idea: Scope
In Python, the scope of a variable is the region of your code where it can be accessed or "seen". Python has two main types of scope that we need to worry about:
- Local Scope: Variables defined inside a function belong to the local scope of that function. They can only be accessed from within that function.
- Global Scope: Variables defined outside of any function belong to the global scope. They can be accessed from anywhere in your code, both inside and outside of functions.
Think of it like a house:
- Global Scope: The public street. Anyone can see what's happening there.
- Local Scope: A private bedroom inside the house. Only the people inside that specific room can see and interact with what's in there.
Local Variables
A local variable is created when a function is called and is destroyed when the function finishes.
Key Rule: If you assign a value to a variable inside a function, Python automatically assumes it's a local variable, unless you explicitly tell it otherwise.

Example: Accessing a Local Variable
def my_function(): # 'message' is a local variable message = "Hello from inside the function!" print(message) my_function() print(message) # This will cause an error!
Output:
Hello from inside the function!
Traceback (most recent call last):
File "<stdin>", line 6, in <module>
NameError: name 'message' is not defined
Why?
- Inside
my_function,messageis created and printed. - Once
my_function()finishes, themessagevariable is destroyed. - When you try to print
messagefrom the global scope, it doesn't exist, resulting in aNameError.
Global Variables
A global variable is defined at the top level of your script. It lives as long as your program is running.
Example: Accessing a Global Variable
You can read a global variable from inside a function without any special keywords.

# 'global_message' is a global variable
global_message = "I am a global variable!"
def read_global():
# We can access the global variable here
print(f"Inside the function: {global_message}")
read_global()
print(f"Outside the function: {global_message}")
Output:
Inside the function: I am a global variable!
Outside the function: I am a global variable!
Why?
The function read_global can "see" the global_message variable because it's in the global scope.
The Problem: Modifying a Global Variable Inside a Function
This is where most confusion arises. What happens if you try to change the value of a global variable inside a function?
The default behavior is that Python will create a new local variable with the same name, instead of modifying the global one.
Example: The "Trap" (Creating a Local Variable)
counter = 10 # This is a global variable
def increment():
# Python sees you are assigning a value to 'counter'
# and assumes you want a NEW local variable named 'counter'.
counter = counter + 1
print(f"Inside the function, counter is: {counter}")
increment()
print(f"Outside the function, counter is still: {counter}")
Output:
Traceback (most recent call last):
File "<stdin>", line 6, in increment
UnboundLocalError: local variable 'counter' referenced before assignment
Wait, why an UnboundLocalError?
- When Python starts executing
increment(), it sees thatcounteris on the left side of an assignment (). - It decides that
countermust be a local variable for this function. - However, when it gets to
counter + 1, it tries to read the localcounterbefore it has been assigned a value. This causes the error.
How to Fix It?
You must explicitly tell Python that you want to use the global version of the variable. You do this with the global keyword.
Example: The Solution (Using the global Keyword)
counter = 10 # This is a global variable
def increment():
# Tell Python: "When I say 'counter', I mean the GLOBAL one."
global counter
counter = counter + 1
print(f"Inside the function, counter is: {counter}")
increment()
print(f"Outside the function, counter is now: {counter}")
Output:
Inside the function, counter is: 11
Outside the function, counter is now: 11
Why?
- The line
global counterinside the function instructs Python to not create a new local variable. - Instead, it tells Python to look for and use the
countervariable from the global scope. - Now,
counter = counter + 1correctly modifies the global variable.
Summary Table
| Scenario | Behavior | How to Modify Global Variable? |
|---|---|---|
| Read a global variable inside a function. | Works. You can access its value. | Not needed. |
| Assign to a variable with the same name as a global variable. | Creates a new local variable. The global variable is untouched. This can cause UnboundLocalError. |
Use the global keyword inside the function. |
| Modify a global variable inside a function. | Creates a new local variable. The global variable is untouched. | Use the global keyword inside the function. |
Best Practices and Advanced Topics
Avoid Modifying Global Variables Directly
While it's possible, directly modifying global variables inside functions is often considered bad practice. It can make your code harder to debug and understand because the function's behavior depends on the state of a variable outside of it.
Better Approach: Pass the global variable as an argument to the function and return the modified value.
# Better Practice: Using Arguments and Return Values
counter = 10
def increment(value):
# This function has no side effects. It's predictable.
return value + 1
# Call the function and assign its return value back to the global variable
counter = increment(counter)
print(f"Counter is now: {counter}")
This approach is cleaner, more testable, and follows the principle of "pure" functions where the output depends only on the input.
global vs. nonlocal (For Nested Functions)
Python has another keyword, nonlocal, which is used for variables in an enclosing (outer) function's scope, not the global scope.
def outer_function():
# 'x' is in the scope of outer_function
x = "outer"
def inner_function():
# We want to modify 'x' from outer_function, not the global one.
nonlocal x
x = "inner"
print(f"Inner function sees: {x}")
inner_function()
print(f"After inner call, outer function sees: {x}")
outer_function()
# print(x) # This would cause a NameError, as 'x' is not in global scope
Output:
Inner function sees: inner
After inner call, outer function sees: inner
global: Refers to the module-level scope.nonlocal: Refers to the nearest enclosing scope (one level up).
Final Rule of Thumb
- If you only need to read a global variable inside a function, you can do so directly.
- If you need to assign or modify a global variable inside a function, you must declare it with the
globalkeyword at the beginning of the function. - Consider if passing arguments and returning values is a cleaner, safer alternative.
