The variable scope determines where a variable can be accessed within a program. Python has four main scopes, arranged in the order of lookup:
1. Four Levels of Scope (LEGB Rule)
-
Local – Local Scope
-
Enclosing – Enclosing Scope
-
Global – Global Scope
-
Built-in – Built-in Scope
2. Local Variables vs Global Variables
1. Local Variables
def calculate_sum(a, b): # result is a local variable, accessible only within the function result = a + b return result
sum_result = calculate_sum(5, 3)print(sum_result) # Output: 8# print(result) # Error: NameError, result is a local variable
2. Global Variables
# Global variable, accessible throughout the moduleglobal_counter = 0
def increment_counter(): # To modify a global variable, use the global keyword global global_counter global_counter += 1
def read_counter(): # Reading a global variable does not require the global keyword return global_counter
increment_counter()print(read_counter()) # Output: 1print(global_counter) # Output: 1
3. Practical Examples of Scope
Example 1: Basic Scope
x = 10 # Global variable
def test_scope(): y = 20 # Local variable print("Inside function - Local variable y:", y) print("Inside function - Global variable x:", x) # Can read global variable
test_scope()print("Outside function - Global variable x:", x)# print("Outside function - Local variable y:", y) # Error: NameError
Example 2: Variable Shadowing
value = "global" # Global variable
def demo_shadowing(): value = "local" # Local variable, shadows the global variable print("Inside function value:", value) # Output: local
demo_shadowing()print("Outside function value:", value) # Output: global
Example 3: Using the global Keyword
count = 0
def increment(): global count # Declare to use the global variable count += 1 print("Inside function count:", count)
increment() # Output: Inside function count: 1increment() # Output: Inside function count: 2print("Final count:", count) # Output: 2
4. Enclosing Scope
def outer_function(): outer_var = "outer" # Enclosing scope variable
def inner_function(): inner_var = "inner" # Local variable print("Inner function access:", outer_var) # Can access enclosing scope print("Inner function variable:", inner_var)
inner_function() # print("Outer function access:", inner_var) # Error: NameError
outer_function()
Using the nonlocal Keyword
def counter(): count = 0
def increment(): nonlocal count # Declare to use the enclosing scope variable count += 1 return count
return increment
my_counter = counter()print(my_counter()) # Output: 1print(my_counter()) # Output: 2
5. Built-in Scope
# Built-in functions and variablesprint(len([1, 2, 3])) # len is a built-in functionprint(max(1, 5, 2)) # max is a built-in function
# Can override built-in functions (not recommended)def len(x): return "Custom len function"
print(len([1, 2, 3])) # Output: Custom len function
# Restore built-in function
del lenprint(len([1, 2, 3])) # Output: 3
6. Best Practices for Scope
1. Avoid Overusing Global Variables
# Not recommendedglobal_data = []
def process_data(): global global_data global_data.append("processed")
# Recommended approachdef process_data_better(input_data): result = input_data.copy() result.append("processed") return result
data = []processed_data = process_data_better(data)
2. Use Function Parameters and Return Values
# Good design: pass data through parameters and return valuesdef calculate_stats(numbers): """Calculate statistics""" return { 'sum': sum(numbers), 'avg': sum(numbers) / len(numbers), 'max': max(numbers) }
data = [1, 2, 3, 4, 5]stats = calculate_stats(data)print(stats)
3. Use Classes to Manage State
class Counter: def __init__(self): self.count = 0 # Instance variable
def increment(self): self.count += 1 return self.count
# Use my_counter = Counter()print(my_counter.increment()) # 1print(my_counter.increment()) # 2
7. Common Errors and Solutions
Error 1: Modifying a Global Variable Without Declaring Global
total = 0
def add_number(n): # total += n # Error: UnboundLocalError global total # Need to add this line total += n
add_number(5)
Error 2: Redefining and Accessing External Variables Within a Function
x = 10
def confusing(): print(x) # Error: UnboundLocalError x = 20 # This line causes x to be treated as a local variable
# Fixdef clear(): global x print(x) # Normal x = 20
8. Scope Lookup Order Verification
def test_legb(): # Verify LEGB lookup order print("Looking up built-in function:", len) # Built-in
global_var = "global"
def inner(): enclosing_var = "enclosing"
def deepest(): local_var = "local" print("Local:", local_var) print("Enclosing:", enclosing_var) print("Global:", global_var) print("Built-in:", len)
deepest()
inner()
test_legb()
Conclusion
| Scope Type | Declaration Keyword | Accessible Range | Usage Scenario |
|---|---|---|---|
| Local Scope | None | Inside Function | Temporary Variables, Function Parameters |
| Enclosing Scope | nonlocal | Between Nested Functions | Closures, Decorators |
| Global Scope | global | Entire Module | Configuration, Constants, Shared State |
| Built-in Scope | None | Everywhere | Python Built-in Functions |
Remember: Use local variables whenever possible, use global variables cautiously, and use enclosing scopes judiciously. Good scope management is key to writing clear and maintainable code.