Python Basics — Local & Global Scope
Local & Global Scope
Every variable in Python lives in a scope — the region of code where it can be accessed. Understanding the difference between local and global scope prevents some of the most common bugs beginners encounter.
Local Variables
Variables created inside a function are local — they only exist while the function is running:
def greet():
message = "Hello!" # local variable
print(message)
greet() # Hello!
# print(message) # NameError: name 'message' is not defined
Each function call gets its own fresh set of local variables:
def counter():
count = 0
count += 1
return count
print(counter()) # 1
print(counter()) # 1 — not 2, because count resets every call
Global Variables
Variables created outside any function, at the module level, are global:
language = "Python" # global variable
def show_language():
print(language) # can READ global variables
show_language() # Python
print(language) # Python — still accessible here too
Accessing Global from Local Scope
Functions can read global variables but cannot assign to them without the global keyword:
name = "Alice"
def greet():
# Reading the global variable — works fine
print(f"Hello, {name}!")
greet() # Hello, Alice!
Variable Shadowing
If you assign to a variable with the same name as a global, Python creates a new local variable that shadows the global:
color = "blue" # global
def paint():
color = "red" # local — shadows the global
print(color) # red
paint()
print(color) # blue — global unchanged
The local color and global color are completely different variables.
UnboundLocalError Explained
This is one of the most confusing errors for beginners:
count = 10
def increment():
count = count + 1 # UnboundLocalError!
return count
# increment() # UnboundLocalError: local variable 'count' referenced before assignment
Why? Python sees count = ... inside the function, so it treats count as local. But on the right side of =, it tries to read count before it’s been assigned — hence the error.
Fixes
# Fix 1: Pass as argument (preferred)
count = 10
def increment(c):
return c + 1
count = increment(count)
print(count) # 11
# Fix 2: Use the global keyword (use sparingly)
count = 10
def increment():
global count
count = count + 1
increment()
print(count) # 11
Local vs Global — Side by Side
x = "global"
def outer():
x = "outer local"
def inner():
x = "inner local"
print(f"inner: {x}")
inner()
print(f"outer: {x}")
outer()
print(f"global: {x}")
# Output:
# inner: inner local
# outer: outer local
# global: global
Each level has its own independent x.
Function Parameters Are Local
def double(n):
n = n * 2 # n is local
return n
value = 5
result = double(value)
print(result) # 10
print(value) # 5 — unchanged
Parameters behave like local variables — assigning to them doesn’t affect the caller.
Watch out with mutable objects: While reassigning a parameter doesn’t affect the caller, mutating a mutable object (like a list) does:
def add_item(lst):
lst.append("new") # mutates the original list
my_list = [1, 2, 3]
add_item(my_list)
print(my_list) # [1, 2, 3, 'new'] — original changed!
Summary
| Concept | Description |
|---|---|
| Local variable | Created inside a function; exists only during that call |
| Global variable | Created at module level; accessible everywhere in the module |
| Shadowing | Local variable with the same name as a global — hides the global |
UnboundLocalError |
Trying to read a local variable before it’s assigned |
| Parameters | Always local to the function |
Next up: LEGB Rule →