Table of Contents
Understanding Scope in Python
In Python, scope determines where in your code a variable can be seen (accessed) and used. In this chapter, you’ll focus on two main kinds of scope:
- Local scope
- Global scope
You’ll also see how scope works with functions, and some common pitfalls to avoid.
Local Scope: Variables Inside Functions
A local variable is a variable that is created inside a function. It:
- Exists only while the function is running.
- Can be used only inside that function.
- Disappears after the function finishes.
Example:
def greet():
message = "Hello!" # local variable
print(message)
greet()
print(message) # This will cause an errorExplanation:
messageis created insidegreet().- Inside
greet(),print(message)works. - Outside the function,
messagedoes not exist, soprint(message)causes aNameError.
You can think of a function as its own “room”; variables created in that room can’t be seen from outside.
Global Scope: Variables Outside Functions
A global variable is a variable that is created outside of all functions (at the top level of a file). It:
- Can be accessed from any function in that file (read-only by default).
- Exists for as long as the program is running.
Example:
message = "Hello from global scope!" # global variable
def show_message():
print(message) # we can read the global variable
show_message()
print(message)Here:
messageis global because it’s defined outside any function.show_message()can read and print the globalmessage.- Code outside functions can also use
message.
Local vs Global with the Same Name
If a variable with the same name exists both globally and locally, Python will use the local one inside the function.
Example:
x = 10 # global variable
def test():
x = 5 # local variable
print("Inside function:", x)
test()
print("Outside function:", x)Output:
Inside function: 5
Outside function: 10- Inside
test(), Python uses localx = 5. - Outside the function, Python uses global
x = 10.
This is called variable shadowing: the local x shadows (hides) the global x inside the function.
Reading Global Variables Inside Functions
You can always read a global variable inside a function (as long as you don’t try to assign to a variable with the same name in that function).
Example:
price = 100
def show_price():
# Only reading price, not assigning to it
print("The price is", price)
show_price()
This works fine because the function is only reading price, not creating or changing a local variable with the same name.
Why Assignment Changes Things
If you assign to a variable name inside a function, Python treats that name as local to that function (unless you explicitly tell Python otherwise). That means you can’t both assign and read the global variable under the same name without extra steps.
Example that causes an error:
count = 0
def increase():
print(count) # trying to read count
count = count + 1 # assigning to count (local)
increase()
This will cause an UnboundLocalError. Why?
- Because
countis assigned insideincrease(), Python decidescountis local in that function. - When Python reaches
print(count), it looks for the localcountfirst, but it hasn’t been assigned yet. - It does not use the global
count, because the function has a local variable namedcount.
To fix this, you can:
- Use a different local variable name, or
- Pass
countas a parameter and return a new value, or - Use the
globalkeyword (explained next).
The `global` Keyword (Changing Global Variables)
If you really need to change a global variable from inside a function, you can use the global keyword.
Syntax inside a function:
global variable_nameThis tells Python:
“When I use variable_name in this function, I mean the global one, not a new local one.”
Example:
counter = 0 # global
def increase():
global counter # use the global counter, not a new local one
counter = counter + 1
increase()
increase()
print(counter) # 2
Now counter is updated globally.
When (and When Not) to Use `global`
Using global can make code harder to understand and debug, because many different parts of your program can change the same variable.
Better approaches:
- Prefer parameters and return values to move data in and out of functions.
- Use
globalonly when you really need shared state (for example, a small script or a constant that won’t change).
Example without global:
def increase(value):
return value + 1
counter = 0
counter = increase(counter)
counter = increase(counter)
print(counter) # 2
This is clearer: increase does not depend on any global state.
The `nonlocal` Keyword (Mention Only)
In nested functions (a function defined inside another function), there is another keyword: nonlocal. It lets you change a variable from an outer function’s scope (not global, not local to the inner function).
You’ll rarely need this as a beginner, but here’s a tiny example so you recognize it:
def outer():
x = 10
def inner():
nonlocal x
x = x + 1
print("Inside inner:", x)
inner()
print("Inside outer:", x)
outer()
Here, nonlocal x tells Python that x comes from outer(), not from inner() and not from the global scope.
The LEGB Rule (Where Python Looks for Variables)
When Python sees a variable name, it checks scopes in this order (LEGB):
- Local – inside the current function.
- Enclosing – in any outer functions (for nested functions).
- Global – at the top level of the file.
- Built-in – names that Python provides (like
len,print).
It stops as soon as it finds the name.
Simple example (without nesting):
x = 100 # global
def demo():
x = 5 # local
print(x)
demo() # prints 5 (local)
print(x) # prints 100 (global)Python:
- Looks in the local scope inside
demo()and findsx = 5. - Outside the function, it uses the global
x = 100.
Scope and Function Parameters
Function parameters behave like local variables inside the function.
Example:
tax_rate = 0.2 # global
def calculate_price(price): # price is a local variable
total = price * (1 + tax_rate) # total is also local
return total
final = calculate_price(50)
print(final)
print(price) # error: price is local to the functionpriceandtotalexist only insidecalculate_price.- Outside the function, you cannot access
priceortotal.
Common Scope Mistakes and How to Avoid Them
1. Expecting Local Variables to Be Global
Mistake:
def create_name():
name = "Alice"
create_name()
print(name) # errorFix: return the value and assign it outside:
def create_name():
return "Alice"
name = create_name()
print(name)2. Overusing Global Variables
Mistake:
total = 0
def add_to_total(x):
global total
total += x
add_to_total(5)
add_to_total(10)
print(total)This works, but logic is hidden and spread out.
Better: use return values:
def add(a, b):
return a + b
total = 0
total = add(total, 5)
total = add(total, 10)
print(total)3. Shadowing Global Names Without Realizing
Mistake:
data = [1, 2, 3]
def process():
data = "not a list anymore" # shadows global data
print(data)
process()
print(data) # still the original list, not changed
If you meant to change the global data, you must either:
- Use
global datainside the function (if really necessary), or - Return a new value and reassign it outside the function.
Practical Guidelines for Using Scope
- Use local variables and parameters inside functions as much as possible.
- Treat global variables mostly as constants (values that don’t change).
- To move data:
- Use parameters to bring data into a function.
- Use return values to bring data out of a function.
- Avoid naming local variables the same as global variables, unless you’re very sure of what you’re doing.
- Remember: if you assign to a variable inside a function, Python treats it as local, unless you declare it
globalornonlocal.
By understanding scope, you can write functions that are easier to read, test, and reuse, without unexpected side effects from variables changing in surprising places.