What Is Scope?
When you create a variable inside a function, something important happens: that variable only exists inside that function. Try to use it outside, and Python won't recognize it. This concept is called scope — the region of code where a variable is visible and accessible.
Local Scope
Variables created inside a function have local scope. They're born when the function runs and die when it ends:
def greet():
message = "Hello!" # Local variable
print(message)
greet() # Prints: Hello!
print(message) # Error! 'message' is not defined
The variable message exists only while greet() is running. Outside the function, it doesn't exist.
Global Scope
Variables created outside any function have global scope. They're accessible throughout your program:
greeting = "Hello" # Global variable
def greet():
print(greeting) # Can read global variables
greet() # Prints: Hello
print(greeting) # Prints: Hello
Global variables can be read from inside functions, but this can get confusing in larger programs.
Same Name, Different Variables
Here's where it gets interesting. A local variable can have the same name as a global variable — but they're completely separate:
message = "Global message"
def show_message():
message = "Local message" # Creates a NEW local variable
print(message)
show_message() # Prints: Local message
print(message) # Prints: Global message
Inside show_message(), Python creates a local message that shadows (hides) the global one. The global message is unchanged.
Why Scope Exists
Scope protects your code. Without it, every variable would be global, and functions could accidentally overwrite each other's data:
# Without scope (hypothetically), this would be chaos:
def calculate_tax():
total = 100 # Oops, overwrote someone else's 'total'!
def calculate_shipping():
total = 50 # Oops, did it again!
With scope, each function has its own private workspace. Variables inside one function can't interfere with variables in another.
Avoiding Common Mistakes
Don't rely on global variables inside functions. It makes code harder to understand and test. Instead, pass values as parameters:
# Harder to follow
tax_rate = 0.08
def calculate_tax(amount):
return amount * tax_rate # Where does tax_rate come from?
# Clearer
def calculate_tax(amount, rate):
return amount * rate # Everything is explicit
When functions receive all their inputs as parameters, they're easier to understand, test, and reuse.