Master Python’s LEGB Rule: Scope Secrets for Faster, Safer Code
This article explains Python’s LEGB rule—Local, Enclosing, Global, Built‑in scopes—detailing each namespace with clear code examples, demonstrating name resolution order, performance impacts, and practical best‑practice tips such as minimizing globals, using nested scopes, and avoiding built‑in overrides.
1. What is the LEGB rule in Python?
Python, like most languages, defines several scopes for variables and functions. The LEGB rule (Local, Enclosing, Global, Built‑in) determines the order in which Python searches these namespaces.
1.1 Local scope
A variable defined inside a function is local and cannot be accessed from outside the function.
def func():
local_var = 10
print(local_var)Use locals() inside a function to inspect its local namespace.
def func():
local_var = 10
print("Local Scope:", locals())
func()1.2 Enclosing scope
An enclosing scope exists only for nested functions; the inner function can access variables from the outer function.
def outer_func():
outer_var = 20
def inner_func():
print(outer_var)
inner_func()1.3 Global scope
Variables defined at the top level of a script are in the global scope and are accessible from any function.
global_var = 30
def func():
print(global_var)1.4 Built‑in scope
The built‑in scope contains objects provided by Python itself, such as len() and print(). These are always available without any import.
2. Name resolution order
When Python encounters a name, it searches the namespaces in the order: Local → Enclosing → Global → Built‑in.
a = "Global"
def outer():
a = "Enclosing"
def inner():
a = "Local"
print("a - inner:", a)
inner()
print("a - outer:", a)
outer()
print("a - global:", a)The built‑in scope is consulted last. The following example shadows the built‑in print and then restores it from globals()['__builtins__']:
def test_print():
print = "Shadowing built-in"
try:
print("This will throw an error because 'print' is now a string, not a function")
except TypeError as e:
print = globals()['__builtins__'].print
print("Caught error:", e)
test_print()3. Impact on performance and memory
Using local variables is faster than globals. The following benchmark shows a ~30% speed‑up when the computation uses a local variable.
sum_global = 0
def sum_numbers_global():
global sum_global
for number in range(1000000):
sum_global += number
def sum_numbers_local():
local_sum = 0
for number in range(1000000):
local_sum += number
return local_sumList comprehensions also benefit from LEGB because the loop variable is local, making them faster than an equivalent for loop.
# for loop version
factor = 2
results = []
for i in range(100):
results.append(i * factor)
# list comprehension version
factor = 2
results = [i * factor for i in range(100)]4. Design insights and best practices
Minimize use of the global namespace . Prefer passing data through functions or encapsulating state in classes.
items = []
def add_item(item):
items.append(item)
def clear_items():
global items
items.clear()Encapsulating the list in a class avoids accidental modifications and improves maintainability.
class ItemManager:
def __init__(self):
self.items = []
def add_item(self, item):
self.items.append(item)
def clear_items(self):
self.items = []
manager = ItemManager()
manager.add_item("apple")
manager.add_item("banana")
print(manager.items)
manager.clear_items()
print(manager.items)When to use nested namespaces?
Nested scopes are useful for creating counters or decorators without resorting to globals.
def call_counter(func):
def wrapper(*args, **kwargs):
wrapper.count += 1
return func(*args, **kwargs)
wrapper.count = 0
return wrapper
@call_counter
def function_to_track():
pass
function_to_track()
function_to_track()
print("Function was called", function_to_track.count, "times.")Avoid overriding built‑in objects
Never overwrite built‑in functions such as print or len, as this can cause confusing bugs.
Summary
Understanding the LEGB rule clarifies Python’s name‑resolution order, helps write more efficient code, and guides better design decisions such as reducing globals, leveraging nested scopes, and protecting built‑in objects.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Code Mala Tang
Read source code together, write articles together, and enjoy spicy hot pot together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
