Global vs Local Scope in Python
Understanding variable scope is crucial for writing clean, bug-free data science code. In 2026, following proper scoping rules helps prevent subtle bugs, improves code maintainability, and makes your functions more predictable and reusable.
TL;DR — Core Rules
- Local scope: Variables defined inside a function
- Global scope: Variables defined outside any function
- Functions can read global variables but cannot modify them without
globalkeyword - Avoid modifying global variables from inside functions
1. Basic Scope Example
total_sales = 0 # Global variable
def process_transaction(amount: float) -> float:
tax_rate = 0.08 # Local variable
total = amount * (1 + tax_rate)
# This would cause UnboundLocalError if we tried to modify global without 'global'
# total_sales += total # ❌ Wrong
return total
def update_total_sales(amount: float) -> None:
global total_sales # Explicitly declare we want to modify global
total_sales += amount
2. Common Data Science Scope Patterns (and Pitfalls)
def run_experiment(data):
model_name = "RandomForest" # Local variable
# Bad practice - modifying global inside function
# global results
# results.append(...)
# Better approach - return values instead
metrics = calculate_metrics(data, model_name)
return metrics
import pandas as pd
# Recommended pattern: Pass data explicitly, return results
def calculate_metrics(df: pd.DataFrame, model_name: str) -> dict:
"""Pure function - no side effects"""
# All variables here are local
accuracy = 0.92
f1_score = 0.89
return {
"model": model_name,
"accuracy": accuracy,
"f1_score": f1_score
}
3. Best Practices for Data Science in 2026
- Avoid global variables in functions whenever possible
- Pass all required data as parameters instead of relying on globals
- Use pure functions that return values instead of modifying global state
- Only use the
globalkeyword in very specific cases (like configuration or counters) - Keep functions self-contained and predictable
- Use dependency injection or configuration objects instead of global variables
How Python Finds a Name
Python looks up names using the LEGB rule: Local, Enclosing, Global, then Built-in. A variable assigned inside a function is local to it unless declared otherwise, so it disappears when the function returns.
Reading a global inside a function works, but assigning to it creates a new local name. The global keyword changes that, yet passing values as parameters and returning results is almost always clearer and easier to test.
Worked Example: Local, Global and Shadowing
The code shows a local variable, an UnboundLocalError, and the cleaner parameter approach.
threshold = 100
def count_large(values):
big = [v for v in values if v > threshold]
return len(big)
print(count_large([50, 150, 200]))
def broken():
try:
threshold += 1
except UnboundLocalError as err:
print("UnboundLocalError:", err)
broken()
def count_large_param(values, limit):
return sum(v > limit for v in values)
print(count_large_param([50, 150, 200], limit=120))
Reading threshold works, but assigning to it inside broken makes Python treat it as local, so it fails before a value exists. Passing limit as a parameter removes the dependency on global state.
Practical Tips
Notebooks make scope problems more likely, because variables from earlier cells remain in the global namespace. A function that accidentally reads such a variable may work in the notebook and fail as soon as it is moved into a script. Restarting the kernel and running all cells from the top is a quick way to catch these hidden dependencies before sharing your work.
Constants are the reasonable exception: module-level values written in capital letters, such as TAX_RATE, are read but never reassigned, so they do not cause the same problems as changing globals.
Common Mistakes
- Changing globals from inside functions.
- Shadowing built-ins such as sum or max with local names.
- Assuming local variables survive after the call.
- Relying on notebook globals that are not defined in scripts.
Quick Summary
- Python resolves names with LEGB.
- Assignment makes a name local.
- global works but hurts testability.
- Prefer parameters and return values.
Conclusion
Scope is one of the most important concepts in Python programming. In data science, following the principle of "explicit is better than implicit" means avoiding global variables in functions and preferring to pass data as parameters and return results explicitly. This approach leads to cleaner, more testable, and more maintainable code.
Next steps:
- Review your current data science scripts and replace any global variable modifications inside functions with proper parameter passing and return values