- What is variable scope — the visibility of variables
- Local variables — variables inside functions
- Global variables — variables accessible everywhere
- Non-Local variables — variables in nested functions
- The LEGB rule — how Python looks up variables
- Best practices — writing clean, maintainable code
What is Variable Scope?
Think of variable scope as the "neighborhood" where a variable lives. Just like people live in different neighborhoods with different rules, variables in Python exist in different scopes that determine where they can be accessed and modified.
💡 Key concept: Variable scope defines the region of your code where a particular variable is visible and can be accessed. Understanding scope is crucial for writing predictable, bug-free code.
Local Variables
Variables Inside Functions
# Local variables are defined inside a function
# They can only be accessed within that function
def my_function():
# This is a local variable
local_var = "I'm local"
print(local_var) # ✅ This works
my_function()
# Output: I'm local
# Trying to access local_var outside the function
# print(local_var) # ❌ NameError: name 'local_var' is not defined
# Each function has its own local scope
def function_one():
value = "Function One"
print(value) # Function One
def function_two():
value = "Function Two"
print(value) # Function Two
function_one()
function_two()
# Local variables are created when the function is called
# and destroyed when the function returns
# Parameters are also local variables
def greet(name): # name is a local variable
greeting = "Hello" # greeting is also local
return f"{greeting}, {name}!"
print(greet("Alice")) # Hello, Alice!
# 'name' and 'greeting' don't exist outside the function
# Local variables take precedence over global ones
global_var = "I'm global"
def show_precedence():
global_var = "I'm local"
print(global_var) # I'm local
show_precedence() # I'm local
print(global_var) # I'm global (unchanged)
Local variables at a glance:
- Defined inside — created within a function body
- Limited visibility — only accessible inside the function
- Short-lived — created when called, destroyed when returns
- Parameters are local — function parameters behave like local variables
- Precedence — local variables overshadow global ones
Quick Check: Where can a local variable be accessed? (Answer: Only inside the function where it's defined)
Global Variables
Variables Accessible Everywhere
# Global variables are defined at the top level of a module
# They can be accessed anywhere in the code
# Defining a global variable
global_var = "I'm accessible everywhere"
def show_global():
print(global_var) # ✅ Accessing global variable
show_global() # I'm accessible everywhere
print(global_var) # I'm accessible everywhere
# Reading global variables is easy
def read_global():
print(f"Reading global: {global_var}")
# Modifying global variables requires the 'global' keyword
def modify_global():
global global_var # Tell Python we want to modify the global
global_var = "I've been modified"
modify_global()
print(global_var) # I've been modified
# Without 'global', Python creates a local variable
def try_to_modify():
global_var = "I'm local" # This creates a new local variable
print(f"Inside function: {global_var}")
try_to_modify() # Inside function: I'm local
print(f"Outside: {global_var}") # Outside: I've been modified (unchanged)
# Global variables can be accessed but not modified without 'global'
def read_only():
print(f"Reading: {global_var}") # This works
# Common use case: configuration settings
APP_NAME = "My Awesome App"
VERSION = "1.0.0"
DEBUG_MODE = True
def show_app_info():
print(f"App: {APP_NAME}")
print(f"Version: {VERSION}")
print(f"Debug: {DEBUG_MODE}")
show_app_info()
Global variables at a glance:
- Defined at top level — outside any function
- Accessible everywhere — can be read from any function
- Modification requires 'global' — use the keyword to change them
- Useful for constants — configuration values, app settings
- Use sparingly — too many globals make code hard to debug
Quick Check: What keyword is needed to modify a global variable inside a function? (Answer: global)
Non-Local Variables
Variables in Nested Functions
# Non-Local variables exist in nested functions
# They are defined in an outer function and accessed in an inner function
# 1. Basic nonlocal example
def outer_function():
outer_var = "I'm from the outer function"
def inner_function():
nonlocal outer_var # Tells Python to use the outer variable
outer_var = "Modified by inner function"
print(f"Inner: {outer_var}")
inner_function()
print(f"Outer after modification: {outer_var}")
outer_function()
# Inner: Modified by inner function
# Outer after modification: Modified by inner function
# 2. Without nonlocal (read-only access)
def outer():
message = "Original"
def inner():
# Reading is fine without nonlocal
print(f"Reading: {message}")
inner()
outer() # Reading: Original
# 3. Without nonlocal (trying to modify creates a new variable)
def outer():
count = 0
def inner():
count = 5 # This creates a new local variable
print(f"Inner count: {count}")
inner()
print(f"Outer count: {count}")
outer()
# Inner count: 5
# Outer count: 0
# 4. With nonlocal (modifies the outer variable)
def outer():
count = 0
def inner():
nonlocal count
count += 1
print(f"Inner count: {count}")
inner()
inner()
print(f"Outer count: {count}")
outer()
# Inner count: 1
# Inner count: 2
# Outer count: 2
# 5. Nonlocal in a real-world example: Counter
def create_counter():
count = 0
def increment():
nonlocal count
count += 1
return count
def decrement():
nonlocal count
count -= 1
return count
def reset():
nonlocal count
count = 0
return count
return increment, decrement, reset
inc, dec, res = create_counter()
print(inc()) # 1
print(inc()) # 2
print(dec()) # 1
print(res()) # 0
Non-Local variables at a glance:
- Used in nested functions — when you need to modify outer function variables
- Requires 'nonlocal' — must be declared to modify
- Read access is free — you can read outer variables without nonlocal
- Not the same as global — nonlocal works within nested functions
- Useful for closures — maintaining state in functions
Quick Check: What keyword is used to modify a variable from an outer (non-global) function? (Answer: nonlocal)
The LEGB Rule
How Python Looks Up Variables
# Python follows the LEGB rule to find variables:
# L - Local
# E - Enclosing (nonlocal)
# G - Global
# B - Built-in
# LEGB in action
# 1. Built-in scope
print("Hello") # print is a built-in function
# 2. Global scope
x = "global"
def outer():
# 3. Enclosing (nonlocal) scope
y = "enclosing"
def inner():
# 4. Local scope
z = "local"
print(f"z: {z}") # Finds z in local scope
print(f"y: {y}") # Finds y in enclosing scope
print(f"x: {x}") # Finds x in global scope
print(f"len: {len}") # Finds len in built-in scope
inner()
outer()
# Demonstrating the lookup order
def demo_lookup():
# Local variable
value = "local"
def inner():
# This will use the local variable
value = "inner local"
print(f"First: {value}") # inner local
inner()
print(f"Second: {value}") # local (outer function variable)
demo_lookup()
# If a variable doesn't exist in any scope
# def missing_var():
# print(undefined_var) # NameError
# You can see the built-in scope
import builtins
print(dir(builtins)[:10]) # Shows some built-in functions
# Shadowing built-ins (not recommended)
# len = "shadow" # Don't do this!
# print(len([1, 2, 3])) # TypeError: str object is not callable
The LEGB lookup order:
- L: Local — variables defined inside the current function
- E: Enclosing — variables in any enclosing functions (nonlocal)
- G: Global — variables defined at the top level of a module
- B: Built-in — Python's built-in names (print, len, etc.)
- First match wins — Python stops at the first matching scope
Quick Check: What does LEGB stand for? (Answer: Local, Enclosing, Global, Built-in)
Best Practices for Variable Scope
Writing Clean, Maintainable Code
# Best practices for working with variable scope
# 1. Prefer local variables over globals
# ✅ Good: Use function parameters
def calculate_total(price, quantity):
total = price * quantity
return total
# ❌ Bad: Using globals unnecessarily
total = 0
def calculate_total_global(price, quantity):
global total
total = price * quantity
return total
# 2. Use constants for configuration
# ✅ Good: Uppercase constants
MAX_RETRIES = 3
API_URL = "https://api.example.com"
TIMEOUT = 30
def fetch_data():
print(f"Connecting to {API_URL}")
print(f"Timeout: {TIMEOUT} seconds")
print(f"Max retries: {MAX_RETRIES}")
# 3. Avoid modifying globals in functions
# ✅ Good: Return values
def process_data(data):
result = data * 2
return result
# ❌ Bad: Modifying globals
data = 10
def process_data_bad():
global data
data = data * 2
# Side effects make code hard to debug
# 4. Use nonlocal sparingly
# ✅ Good: Only when necessary (closures)
def create_counter():
count = 0
def increment():
nonlocal count
count += 1
return count
return increment
# ❌ Bad: Using nonlocal unnecessarily
def outer():
x = 10
def inner():
nonlocal x # Not needed if you're just reading
return x
# 5. Keep functions small and focused
# ✅ Good: Small functions with clear purpose
def get_user_data(user_id):
return {"id": user_id, "name": "Alice"}
def validate_user_data(data):
return "name" in data
def process_user(user_id):
data = get_user_data(user_id)
if validate_user_data(data):
return data
return None
# 6. Use meaningful variable names
# ✅ Good: Clear, descriptive names
user_count = 0
total_revenue = 0.0
is_active = True
# ❌ Bad: Ambiguous names
x = 0
y = 0.0
z = True
Best practices summary:
- Prefer local variables — they're safer and more predictable
- Use constants for globals — uppercase names for configuration
- Avoid modifying globals — use return values instead
- Use nonlocal sparingly — only when truly needed for closures
- Keep functions small — easier to understand scope
- Use clear names — descriptive names make scope relationships clearer
Quick Check: What's the best practice for using global variables? (Answer: Use them sparingly, preferably as read-only constants)
Try It Yourself
Experiment with variable scope in the editor below. Try modifying the variables and see what happens.
VARIABLE SCOPE PRACTICE
========================================
1. GLOBAL VARIABLE
User added. Total: 1
User added. Total: 2
Final user count: 2
2. LOCAL VARIABLE
Hello, Alice!
3. NON-LOCAL VARIABLE
Increment: 1
Increment: 2
Decrement: 1
4. LEGB RULE DEMO
Local: Local
Enclosing: Enclosing
Global: Global
Built-in: 3
Variable scope practice complete!
You've Got It!
You now understand variable scope in Python — local, global, and non-local variables. You know the LEGB rule and how to write clean code with proper scope management.
Quick Quiz
Test what you've learned:
Frequently Asked Questions
What is the difference between global and nonlocal?
Can I read a global variable without using the global keyword?
Why should I avoid using global variables?
What's a common interview question about variable scope?
Can I have a variable with the same name in different scopes?
What happens if I modify a list or dictionary global variable?
Where to Go From Here
Now that you understand variable scope, check out these related topics:
Lambda Functions
Learn about anonymous functions and their use cases.
Learn More →📝 Assignments
Practice what you've learned with assignments.
Learn More →Python Modules
Learn how to organize code into modules.
Learn More →