Table of Contents
I once spent several days debugging a Python issue where variables had unexpected values.
My code looked correct, individual functions worked as expected, and tests passed. But when everything ran together, variables took on values I never assigned, and functions behaved differently than I expected.
The issue was that I didn't understand how Python finds variables.
Specifically, I didn't know the LEGB rule, the systematic way Python searches for variable names across different scopes. Once I learned it, scope-related bugs became much easier to identify and fix.
This article will teach you the LEGB rule clearly, directly, with real examples. No jargon. No abstract explanations that leave you more confused.
You'll learn exactly how Python resolves variable names, why your code behaves the way it does, and how to avoid the scope-related bugs that trip up so many developers.
What Is the LEGB Rule?
The LEGB rule is Python's search strategy for finding variables. Think of it as a four-step checklist Python follows every time it sees a variable name in your code.
LEGB stands for the four scopes Python checks, in this specific order:
- L – Local: Variables defined inside the current function
- E – Enclosing: Variables from outer functions (in nested functions)
- G – Global: Variables defined at the module level
- B – Built-in: Python's built-in functions and constants
Python searches these scopes from top to bottom, stopping at the first match. If a variable exists in multiple scopes, Python uses the one it finds first in this order, which is why local variables can "hide" global ones.

If Python doesn't find the variable name in any of these four scopes, you get a NameError.
Why the LEGB Rule Matters
You might be thinking: "My code works fine. Why do I need to learn another rule?"
Here's the thing: LEGB isn't optional knowledge. Every time Python executes your code, it's using this rule to resolve every variable name. When you don't understand it, you're flying blind, and that's when bugs creep in.
Knowing the LEGB rule gives you:
- Faster debugging: When a variable has the wrong value, you'll know exactly where Python found it
- Clearer code: You'll write functions with explicit, predictable behaviour
- Fewer mistakes: You'll avoid accidentally shadowing global variables or built-in functions
- Better design choices: You'll know when (and when not) to use
globalandnonlocal
Without understanding LEGB, your Python code works more by accident than by design. With it, you write code that behaves exactly how you intend.
Local Scope (L)
The local scope is the innermost scope. It contains variables defined inside a function.
Example
def greet():
message = "Hello"
print(message)
greet()
Here, message is a local variable. It only exists while the function is running.
Trying to access it outside the function will fail:
print(message) # NameError: name 'message' is not defined
Key Points About Local Scope
- Created when a function is called
- Destroyed when the function returns
- Has the highest priority in the LEGB lookup order
If a variable exists locally, Python will not look elsewhere.
Enclosing Scope (E)
The enclosing scope exists when you have nested functions, meaning a function inside another function.
This scope contains variables from the outer function, but not the global scope.
Example
def outer():
name = "Alice"
def inner():
print(name)
inner()
outer()
Here’s what happens:
inner()looks forname- It doesn’t find it in its local scope
- Python checks the enclosing scope (
outer) nameis found and printed
Global Scope (G)
The global scope contains variables defined at the top level of a module (outside any function).
Example
pi = 3.14
def area(radius):
return pi * radius ** 2
print(area(5))
Here:
piis not local toarea- It’s not in an enclosing scope
- Python finds it in the global scope
Important Notes About Global Scope
- Each module has its own global scope
- Global variables are shared across all functions in the module
- Overusing globals makes code harder to test and maintain
Built-in Scope (B)
The built-in scope contains names that are always available in Python, such as:
printlenrangeintlist
These names live in the builtins module.
Example
numbers = [1, 2, 3]
print(len(numbers))
Python resolves len by checking each scope in LEGB order until it finds the name. Since len isn't defined locally, in an enclosing function, or globally, Python finds it in the built-in scope.
Important Scope Rules
It’s important to understand a few practical scope rules that often surprise developers. These rules aren’t theoretical edge cases, they directly affect how your code behaves and are a common source of subtle bugs if you’re not aware of them.
Loops Don't Create New Scopes
Unlike some languages, Python loops do not create a new scope. Variables assigned inside loops belong to the surrounding scope.
x = 10
for i in range(3):
x = i
print(x) # 2 (not 10!)
The loop variable i and any assignments inside the loop affect the enclosing scope. This is why x ends up as 2 (the last value assigned in the loop).
List Comprehensions Do Create Scopes
However, list comprehensions do have their own local scope in Python 3:
x = 10
values = [x for x in range(5)]
print(x) # 10 (unchanged!)
The x inside the comprehension is separate from the outer x. This prevents the loop variable from "leaking" into your surrounding code, which is generally what you want.
Best Practices for Working with Scope
- Keep functions small and focused
- Avoid global variables
- Pass values explicitly via parameters
- Use descriptive variable names to prevent collisions
Final Thoughts
The LEGB rule isn't just theory, it's the mechanism Python uses every single time it resolves a variable name. Understanding it transforms confusing bugs into obvious scope issues.
When you understand how Python searches for variables, you gain a powerful advantage: you can debug faster by knowing exactly where Python will find (or fail to find) a variable, and you can write clearer, more predictable code.
The next time a variable behaves unexpectedly, remember: Python is following the LEGB rule. Trace through the scopes, and you'll find the answer.
Want to Go Deeper?
This article covers the essentials, but there's so much more to master. Want a complete guide with advanced examples, common pitfalls, and practical patterns?
Get my free PDF guide on Python Variable Scope, it includes everything you need to master LEGB, closures, decorators, and never waste hours debugging scope issues again.
Follow me on Twitter: https://twitter.com/DevAsService
Follow me on Instagram: https://www.instagram.com/devasservice/
Follow me on TikTok: https://www.tiktok.com/@devasservice
Follow me on YouTube: https://www.youtube.com/@DevAsService
