Variable Scope

Where a variable lives and who can see it

Beginner 9 min

In this lesson

Scope is the answer to ‘where can I use this variable?’ Variables created inside a function are private to that function. Understanding scope prevents a whole category of confusing bugs.

Explain it like I’m 5

Each function has its own private notebook. Things it jots down disappear when it finishes, and other functions can’t read its notebook. To share, you pass notes in and hand results back.

Local scope: private by default

A variable assigned inside a function is local: it exists only while the function runs and can’t be seen from outside. Two functions can each have a variable called total without interfering, because each total lives in its own scope. When the function returns, its local variables are gone.

Example
def make_total():
    total = 5      # local to this function
    total = total + 1
    return total

result = make_total()
print(result)
print(total)  # error: total doesn't exist out here
Output
6
NameError: name 'total' is not defined
A local variable can't be seen outside its function.

Global scope and reading outer variables

Variables defined at the top level of your file are global. A function can read a global variable, but if it assigns to a name, Python treats that name as local to the function. This is why a function can use a global constant but can’t accidentally overwrite your top-level variables just by assigning.

Example
TAX_RATE = 0.2  # a global constant

def with_tax(price):
    return price + price * TAX_RATE  # reads the global

print(with_tax(100))
Output
120.0
Functions can read global constants.

The clean pattern: pass in, return out

Rather than relying on globals, the reliable approach is to pass values in as arguments and return results out. This keeps each function self-contained and easy to test: its behaviour depends only on its inputs, not on hidden outside state. Reach for globals sparingly — usually only for constants.

This counter doesn't accumulate because each call resets the local total. Fix it by passing the running total in and returning the new one.

def add_points(points):
    total = 0
    total = total + points
    return total

score = add_points(10)
score = add_points(5)
print(score)

The global keyword (and why to avoid it)

If you truly must reassign a global from inside a function, the global keyword allows it. But code that changes globals is harder to follow and debug, because any function might alter shared state. Prefer returning a new value and reassigning at the top level instead.

The LEGB rule: where Python looks for a name

When you use a name, Python searches four scopes in a fixed order — Local (inside the current function), Enclosing (an outer function wrapping this one), Global (the top level of the file), and Built-in (names like print and len). It uses the first match it finds.

That order — ‘LEGB’ — explains why a local variable can ‘shadow’ a global of the same name, and why print works everywhere: it lives in the built-in scope, the last place Python looks.

Example
x = "global"

def outer():
    x = "enclosing"
    def inner():
        print(x)      # no local x, so Python looks outward
    inner()

outer()
print(x)              # the global x is untouched
Output
enclosing
global
inner() finds the nearest x by searching outward.

Common mistake: Expecting a function to change an outer variable by assigning a local

Why it happens:

Assigning x = ... inside a function creates a new local x; it doesn’t touch the global of the same name.

How to fix it:

Return the new value and reassign it outside: x = update(x). Avoid relying on functions to mutate outer variables.

A variable assigned inside a function is…

What's the recommended way to get data into and out of a function?

Mini exercise (medium)

Without using global, write increment(value) that returns value + 1. Use it to take a top-level count = 0 up to 3 by reassigning.

Do it here. Finish the code below and press Run to try your answer right in the browser — no setup needed.

def increment(value):
    # return value + 1 (no global!)
    return value

count = 0
# TODO: call increment three times, reassigning count each time
print(count)

What to learn next

You learned the difference between local and global scope, why variables inside a function are private, how a function can read outer variables, and why passing values in and returning them out is cleaner than global. You incremented a counter by reassigning it from a function’s return value, no global needed.

With functions and scope understood, you can start pulling in code written by others and by yourself. Modules and Imports covers the import statement, the standard library that ships with Python, importing your own files, and what pip packages are. When you’re ready, continue to the next lesson.