In our previous posts on scope (Post #94, #95, and #96), we’ve seen that variables can exist in different “workspaces”—primarily the local scope inside a function and the global scope outside of any function.
But what happens when you use a variable name? How does Python decide which variable you’re referring to, especially if the same name is used in different scopes?
Python has a simple but strict set of rules for this lookup process, known by the acronym LEGB. In this post, we’ll break down this rule to demystify Python’s variable search path.
The LEGB Search Path
When you use a variable name, Python tries to find it by searching up to four distinct scopes in a specific order. This order is the LEGB rule:
- Local
- Enclosing
- Global
- Built-in
Python checks these scopes in that exact order. The very first time it finds the variable name it’s looking for, it stops the search and uses that variable.
Breaking Down the LEGB Acronym
L: Local Scope
This is the first place Python looks. The local scope is the innermost scope, containing all the variables, including parameters, that are defined inside the currently running function. As we learned in Post #95, these variables are temporary and private to that function call.
E: Enclosing Scope
If the variable isn’t found in the local scope, Python looks in the enclosing scope. This is the scope of any outer functions. This scope only exists if you have a nested function (a function defined inside another function). The inner function can see variables defined in the outer function’s scope.
G: Global Scope
If the search continues, Python next checks the global scope. This is the top-level scope of your script, containing all the global variables you’ve defined outside of any function (as we saw in Post #96).
B: Built-in Scope
Finally, if the name hasn’t been found anywhere else, Python checks the built-in scope. This special scope contains all the names that are built directly into the Python language, like the print()
and len()
functions, and types like str
, int
, and list
. This is why you can call print()
from anywhere without having to define it yourself.
A Complete Example
Let’s see all four scopes in action in a single script.
# B: Built-in scope (contains print, len, etc.)
# G: Global scope
x = "I am global"
def outer_function():
# E: Enclosing scope for inner_function
x = "I am enclosing"
def inner_function():
# L: Local scope
x = "I am local"
print(x) # Python starts its search for 'x' here
inner_function()
outer_function()
When we run this, the output is I am local
. Let’s trace Python’s search:
- L (Local): When
print(x)
is executed, Python first checks the local scope ofinner_function
. It finds a variablex
defined right there (x = "I am local"
)! - Stop! Because it found a match, the search stops immediately. The local variable “shadows” all the others.
Now, let’s see what happens if we comment out the local variable:
# ... (same global and outer function setup)
def inner_function():
# x = "I am local" # This is now commented out
print(x)
# ...
The output is now I am enclosing
. The search path was:
- L (Local): Python checks
inner_function
‘s scope. Nox
is found. - E (Enclosing): Python looks outward to the scope of
outer_function
. It finds anx
variable there! - Stop! The search ends, and it prints the value from the enclosing scope.
If we were to also comment out the x
in outer_function
, the search would continue (L -> E -> G) and it would find and print the global x
.
What’s Next?
The LEGB rule provides a clear and predictable hierarchy for how Python finds your variables. It always starts with the most specific, local scope and works its way outward to the most general, built-in scope. Understanding this rule is key to debugging scope-related issues.
Now that we have a full picture of how functions and variables interact, it’s time to focus on a crucial professional practice: documenting our code. How do we write helpful descriptions for our functions so that others (and our future selves) can understand what they do without reading every line of code? In Post #99, we will learn the power of docstrings.
Author

Experienced Cloud & DevOps Engineer with hands-on experience in AWS, GCP, Terraform, Ansible, ELK, Docker, Git, GitLab, Python, PowerShell, Shell, and theoretical knowledge on Azure, Kubernetes & Jenkins. In my free time, I write blogs on ckdbtech.com