Python Tutorials

Python Variable Scope : Local, Global & The Global Keyword

Imagine you are staying in a large hotel. Your electronic room key is programmed to open exactly one door—your specific room. If you try to use it on your neighbor’s door or the kitchen downstairs, it will fail. However, the hotel manager holds a master key that can open any door in the entire building.

In Python, variables work the exact same way. When you create a variable, Python places limits on where that variable is allowed to be “seen” or used. Some variables are like room keys, locked exclusively inside the function where they were created. Other variables are like master keys, accessible from anywhere in your entire file.

Understanding this concept—known as Variable Scope—is the secret to preventing mysterious bugs where Python suddenly claims a variable “is not defined” or holds the wrong data.

What is Variable Scope?

In Python, Variable Scope determines the accessibility and lifetime of a variable within different parts of your code. Python strictly follows the LEGB Rule to resolve variable names, searching in this specific order:

  1. Local: Variables defined within the current function.
  2. Enclosing: Variables defined inside outer/nested functions.
  3. Global: Variables defined at the top level of a script or module.
  4. Built-in: Pre-assigned names in Python (like print() or len()).

If Python searches all four levels and cannot find the variable, it raises a fatal NameError.

Syntax & Basic Usage

When a variable is created directly in the main body of your script, it is Global. When a variable is created inside an indented function block, it is Local.

# This is a GLOBAL variable. It exists everywhere in the file.
company_name = "TechNova"

def display_employee_info():
    # This is a LOCAL variable. It ONLY exists inside this function.
    employee_role = "Software Engineer"
    
    # The function can freely read the global variable alongside its local ones
    print(f"Role: {employee_role} at {company_name}")

display_employee_info()

# Expected Output:
# Role: Software Engineer at TechNova

Code language: PHP (php)

How Python Function Arguments Affect Variable Scope

Understanding how local and global variables interact, clash, and override one another is a critical skill for any Python developer. Let’s explore the exact boundaries of scope.

1. The Trap of Local Scope

A local variable is born when a function is called, and it is instantly destroyed when the function finishes running. You absolutely cannot access a local variable from the global space.

def process_secure_payment():
    # This variable is highly secure and locked inside the function
    credit_card_token = "tok_12345ABC"
    print("Processing token inside function...")

# We execute the function
process_secure_payment()

# ❌ THE TRAP: Trying to access the local variable from the outside
# print(credit_card_token)

# Expected Output:
# Processing token inside function...
# Error if uncommented: NameError: name 'credit_card_token' is not defined

Code language: PHP (php)

2. Variable Shadowing (Name Clashes)

What happens if you have a Global variable and a Local variable with the exact same name? Python prioritizes the Local variable. The local variable temporarily “shadows” (hides) the global one, but it does not permanently overwrite it.

# 1. Global Variable
player_health = 100

def drink_health_potion():
    # 2. Local Variable with the EXACT SAME NAME
    # This creates a temporary clone; it does NOT change the global health!
    player_health = 150 
    print(f"Health inside function (Local): {player_health}")

drink_health_potion()

# 3. The global variable remains completely untouched!
print(f"Health outside function (Global): {player_health}")

# Expected Output:
# Health inside function (Local): 150
# Health outside function (Global): 100

Code language: PHP (php)

3. The global Keyword

If you actively want a function to overwrite or modify a global variable, you must explicitly ask Python for the master key. You do this by declaring the global keyword before using the variable inside the function.

# Global variable tracking total business revenue
total_revenue = 0.0

def process_sale(sale_amount):
    # We explicitly tell Python: "Do not create a local clone. Use the global one."
    global total_revenue 
    
    # Now, modifying this variable permanently changes it globally
    total_revenue += sale_amount
    print(f"Sale processed: ${sale_amount}")

print(f"Starting Revenue: ${total_revenue}")
process_sale(50.00)
process_sale(120.50)
print(f"Ending Revenue: ${total_revenue}")

# Expected Output:
# Starting Revenue: $0.0
# Sale processed: $50.0
# Sale processed: $120.5
# Ending Revenue: $170.5

Code language: PHP (php)

4. The nonlocal Keyword (Nested Functions)

Sometimes you write a function inside another function. If the inner function needs to modify a variable created by the outer function, you use the nonlocal keyword. It acts as a bridge between nested scopes.

def configure_user_settings():
    # This is an "Enclosing" variable
    theme_color = "Light"
    
    def enable_dark_mode():
        # We tell Python: "Use the variable from the outer function"
        nonlocal theme_color
        theme_color = "Dark"
        print("Settings updated to Dark Mode.")
        
    enable_dark_mode()
    print(f"Current Theme confirmed as: {theme_color}")

configure_user_settings()

# Expected Output:
# Settings updated to Dark Mode.
# Current Theme confirmed as: Dark

Code language: PHP (php)

Real-World Practical Examples

Scenario 1: Authentication State Tracking

In basic applications, a global variable is often used to track the session state across the entire script, allowing different functions to grant or deny access based on that global state.

# Global state tracker
is_user_logged_in = False
current_user = None

def login(username, password):
    global is_user_logged_in, current_user
    
    # Simulating a database check
    if username == "admin" and password == "secret123":
        is_user_logged_in = True
        current_user = username
        print(f"Success: '{current_user}' has logged in.")
    else:
        print("Error: Invalid credentials.")

def view_dashboard():
    # We only need to READ the global variables here, so 'global' keyword isn't strictly required
    if is_user_logged_in:
        print(f"Welcome to the secure dashboard, {current_user}!")
    else:
        print("Access Denied: Please log in first.")

# Testing the flow
view_dashboard()
login("admin", "wrong_password")
login("admin", "secret123")
view_dashboard()

# Expected Output:
# Access Denied: Please log in first.
# Error: Invalid credentials.
# Success: 'admin' has logged in.
# Welcome to the secure dashboard, admin!

Code language: PHP (php)

Scenario 2: Rate Limiting and Analytics Counters

Global variables are excellent for keeping a running tally of events that happen across various, disconnected functions in your code.

# Global counter for API requests
api_request_count = 0
MAX_REQUESTS = 3 # Constants (all caps) are typically global

def fetch_weather_data(city):
    global api_request_count
    
    if api_request_count >= MAX_REQUESTS:
        print(f"Rate Limit Exceeded. Cannot fetch data for {city}.")
        return
        
    api_request_count += 1
    print(f"[{api_request_count}/{MAX_REQUESTS}] Fetching weather for {city}...")

fetch_weather_data("Seattle")
fetch_weather_data("Tokyo")
fetch_weather_data("London")
fetch_weather_data("Paris") # This one will fail

# Expected Output:
# [1/3] Fetching weather for Seattle...
# [2/3] Fetching weather for Tokyo...
# [3/3] Fetching weather for London...
# Rate Limit Exceeded. Cannot fetch data for Paris.

Code language: PHP (php)

Best Practices & Common Pitfalls

  • The UnboundLocalError Trap: This is the most common bug beginners face. If you try to read a global variable and then modify it inside a function without declaring global, Python gets confused and crashes.# ❌ BAD CODE: count = 5 def add_one(): count = count + 1 # Crashes with UnboundLocalError! # ✅ GOOD CODE: def add_one(): global count count = count + 1
  • Avoid Globals When Possible: While the global keyword is powerful, overusing it is considered a bad practice (often called “Spaghetti Code”). If too many functions are modifying the same global variable, tracking down bugs becomes a nightmare.
  • Prefer Returns and Parameters: Instead of using global variables, it is much safer to pass data into a function via parameters, and pass the result back out using a return statement. This keeps your functions modular, predictable, and easy to test.

Summary

  • Scope determines where in your code a variable can be seen and used.
  • Global Variables are defined outside of all functions and can be read from anywhere in the file.
  • Local Variables are defined inside a function and are completely erased from memory the moment the function finishes running.
  • Variable Shadowing occurs when a local variable has the same name as a global variable, temporarily overriding it locally without changing the global data.
  • You must use the global keyword inside a function if you intend to permanently modify a global variable’s value.
  • You must use the nonlocal keyword to modify a variable created by an enclosing (outer) function from within a nested (inner) function.

Leave a Comment