Scope decides where a Python variable can be seen: a name created inside a function is local, and a name at the top of a file is global. Python looks names up in Local, Enclosing, Global, then Built-in scope, the LEGB rule.
rate = 0.0625 # global
def checkout(price):
rate = 0.0825 # local: hides the global inside this function
return price * (1 + rate)
These examples ran on Python 3.12.5, and the screenshots come straight from the Command Prompt. The tax rates are real Texas and Austin sales tax figures.
Below you’ll see each scope in action, when you need global and nonlocal, and the scope surprises that trip up people coming from other languages.
The LEGB rule: how Python looks up a variable
Every time you use a name, Python checks the scopes from the inside out and stops at the first match:
| Scope | What lives there | Example |
|---|---|---|
| Local | Names assigned inside the current function | subtotal in a function |
| Enclosing | Names in any outer function, for nested functions | tax_rate in checkout() |
| Global | Names at the top level of the module | tax_rate = 0.0625 |
| Built-in | Python’s own names | len, print, list |
Here are all four in one short program. line_total() has no tax_rate of its own, so it finds the enclosing one before the global:
tax_rate = 0.0625 # Global: the Texas state rate
def checkout(price):
tax_rate = 0.0825 # Enclosing (for line_total): Austin's combined rate
def line_total():
return round(price * (1 + tax_rate), 2) # Local first, then Enclosing
return line_total()
print("checkout(100):", checkout(100))
print("global tax_rate:", tax_rate) # untouched
print("len('Austin'):", len("Austin")) # len lives in the Built-in scope
Output:
checkout(100): 108.25
global tax_rate: 0.0625
len('Austin'): 6
Notice that the local assignment in checkout() didn’t touch the global. It created a new name that only exists inside that function.
Local variables only exist inside their function
A local variable is created when the function runs, and it’s gone when the function returns. Try to use it afterward and you get a NameError:
def order_total():
subtotal = 59.97 # local to order_total
return round(subtotal * 1.0825, 2)
print("order_total():", order_total())
try:
print(subtotal) # gone once the function returned
except NameError as err:
print("NameError:", err)
Output:
order_total(): 64.92
NameError: name 'subtotal' is not defined
subtotal existed only while order_total() was running.If you need a value from inside a function, return it. Accessing variables outside a function covers the other options, and NameError: name is not defined explains the error itself.
Global variables in Python: reading vs assigning
Any function can read a global variable. Assigning to one is different: without the global keyword, an assignment creates a local variable instead.
visits = 0
def show_visits():
print("reading a global is fine:", visits)
def add_visit():
global visits # needed to ASSIGN to the global
visits += 1
show_visits()
add_visit()
add_visit()
print("visits after two calls:", visits)
Output:
reading a global is fine: 0
visits after two calls: 2
Leave out global visits and add_visit() raises UnboundLocalError, because visits += 1 makes visits local before it has a value.
I keep globals for constants and configuration. For anything that changes, passing values in and returning them is easier to follow; setting global variables in functions has more examples.
The nonlocal keyword for nested functions
global skips straight to the module level. When the variable belongs to an outer function, you need nonlocal instead:
def make_cart():
items = 0
def add(qty):
nonlocal items # rebind the enclosing function's name
items += qty
return items
return add
add = make_cart()
add(2)
print("items in cart:", add(3))
Output:
items in cart: 5
The inner function remembers items between calls; that’s how closures keep state without a global. Calling a function within a function shows more nested-function patterns.
Do if statements and for loops have their own scope in Python?
No, and that’s a surprise if you know C, Java or JavaScript. Only functions, classes, modules and comprehensions create a new scope:
# if and for blocks do NOT create a new scope
if True:
status = "shipped"
print("set inside if :", status)
for i in range(3):
pass
print("loop variable after the loop:", i)
# a comprehension DOES have its own scope
squares = [n * n for n in range(3)]
try:
print(n)
except NameError as err:
print("comprehension variable:", err)
Output:
set inside if : shipped
loop variable after the loop: 2
comprehension variable: name 'n' is not defined
status and i survived their blocks. The comprehension’s n didn’t.So after for i in range(3), i is still 2. That’s handy sometimes, but it can also hide a bug if you reuse the name later and forget it already has a value.
List comprehensions are the exception: their loop variable stays inside. Python list comprehension goes deeper on that syntax.
Shadowing a built-in variable: ‘list’ object is not callable
Built-ins sit in the last scope Python checks, so any global with the same name hides them, and you won’t get a warning. Naming a variable list is the classic mistake:
list = ["Austin", "Denver"] # hides the built-in list()
try:
cities = list("Boston")
except TypeError as err:
print("TypeError:", err)
del list # removes the global, so the built-in is visible again
print(list("Boston"))
Output:
TypeError: 'list' object is not callable
['B', 'o', 's', 't', 'o', 'n']
list exists, list("Boston") calls your list instead of the built-in.del list fixes it in the moment, but the real fix is a better name. The same goes for str, dict, id, sum and input; Python naming conventions has safer options.
Class scope: why methods can’t see class variables directly
A class body has its own scope, but it isn’t an enclosing scope for the methods inside it. A method has to reach class variables through self or the class name:
class Store:
tax = 0.0825
def price_with_tax(self, price):
try:
return price * (1 + tax) # a bare name doesn't see the class body
except NameError as err:
return f"NameError: {err}"
def price_fixed(self, price):
return round(price * (1 + self.tax), 2) # go through self (or Store.tax)
shop = Store()
print(shop.price_with_tax(100))
print(shop.price_fixed(100))
Output:
NameError: name 'tax' is not defined
108.25
The bare name tax fails because the lookup goes from the method straight to the global scope, skipping the class. Class vs instance variables explains how self.tax finds it.
How to check if a variable is local or global
locals() and globals() return the names in each scope as dictionaries, so you can test membership directly:
tax_rate = 0.0625
def checkout(subtotal):
shipping = 5.99
print("locals():", locals())
print("'tax_rate' in globals():", "tax_rate" in globals())
print("'shipping' in globals():", "shipping" in globals())
checkout(40)
Output:
locals(): {'subtotal': 40, 'shipping': 5.99}
'tax_rate' in globals(): True
'shipping' in globals(): False
It’s useful for debugging, but you’ll rarely need it in normal code. If you find yourself checking whether a global exists, it’s usually a sign the value should be passed in instead.
Python variable scope: quick reference
| You want to | Do this |
|---|---|
| Read a global inside a function | Just use the name |
| Assign to a global inside a function | global name first |
| Assign to an outer function’s variable | nonlocal name first |
| Use a class variable in a method | self.name or ClassName.name |
| Get a value out of a function | return it |
| Check where a name lives | name in locals() / name in globals() |
| Avoid hiding a built-in | Don’t name variables list, str, sum, id |
For more on variables and functions, try these next:
- Set global variables in Python functions
- Access variables outside a function
- Class vs instance variables in Python
- Static variables in Python functions
- Variables in Python
Frequently asked questions
What is variable scope in Python?
Scope is the region of a program where a name can be used. Python has four: local, enclosing, global and built-in, searched in that order (the LEGB rule).
What’s the difference between local and global variables in Python?
A local variable is created inside a function and only exists while it runs. A global variable is defined at the top level of a module and can be read anywhere in it.
When do I need the global keyword?
Only when a function assigns to a global variable. Reading one needs no keyword; assigning without global creates a local instead.
What does nonlocal do in Python?
It lets a nested function assign to a variable in its enclosing function, rather than creating a new local one.
Do for loops create a new scope in Python?
No. The loop variable and anything assigned in the loop stay available after it ends. Functions, classes, modules and comprehensions create scopes; if and for blocks don’t.
Can a method use a class variable without self?
No. Use self.name or ClassName.name. The class body isn’t an enclosing scope for its methods; the Python tutorial on scopes and namespaces explains why.
Bijay Kumar is a 13-time Microsoft MVP with more than 18 years in software development, and the founder of Python Guides and TSinfo Technologies. He started out building .NET and SharePoint solutions at HP, TCS and KPIT before moving into Python, machine learning and AI, and he also builds web apps with TypeScript and React. He writes the tutorials here himself, and every example is run before publishing so you see the real output. More about Bijay · Microsoft MVP profile · LinkedIn