How to Access Variables Outside a Function in Python

To access variables outside a function in Python, return the value from the function and store the result in a variable where you called it. A local variable disappears when the function ends, but the value you return doesn’t:

def get_total():
    total = 84.50
    return total

total = get_total()   # 84.5, usable here

I tested each snippet on Python 3.12.5 in the Command Prompt, so the outputs below are real.

In this tutorial, we’ll cover return values, function attributes, closures, classes, modules and the global keyword.

Why can’t you use a local variable outside its function?

A name assigned inside a function is local. Python creates it when the call starts and throws it away when the call returns, so code after the call can’t see it:

def checkout():
    order_total = 84.50      # local: lives only while checkout() runs
    print(f"Inside: ${order_total:.2f}")

checkout()
print(f"Outside: ${order_total:.2f}")

Output:

Inside: $84.50
Traceback (most recent call last):
  File "C:\pyguides\checkout_scope.py", line 6, in <module>
    print(f"Outside: ${order_total:.2f}")
                       ^^^^^^^^^^^
NameError: name 'order_total' is not defined
Command Prompt traceback showing NameError when a Python local variable is used outside its function
The print inside the function works, but the line outside raises NameError because order_total no longer exists.

The full lookup order (local, enclosing, global, built-in) is in my guide to Python variable scope.

Return the value from a Python function (the best way)

Returning is the cleanest fix, and you can return several values as a tuple and unpack them in one line:

def checkout(prices, tax_rate):
    subtotal = sum(prices)
    tax = round(subtotal * tax_rate, 2)
    total = subtotal + tax
    return subtotal, tax, total        # hand the values back

subtotal, tax, total = checkout([19.99, 45.00, 12.51], 0.0825)
print(f"Subtotal: ${subtotal:.2f}")
print(f"Tax:      ${tax:.2f}")
print(f"Total:    ${total:.2f}")

Output:

Subtotal: $77.50
Tax:      $6.39
Total:    $83.89
Command Prompt output of a Python function returning subtotal, tax and total to the caller
The three values computed inside checkout() come back to the caller and print as dollar amounts.

For dictionaries, named tuples and other ways to send back more than one value, see returning multiple values from a function in Python.

Store values as attributes on the function object

Functions are objects, so you can hang attributes on them and read them from outside:

def ship_order(state):
    ship_order.count += 1
    ship_order.last_state = state      # store it ON the function object

ship_order.count = 0                   # set before the first call

ship_order("TX")
ship_order("CA")
ship_order("NY")
print("orders shipped:", ship_order.count)
print("last state:", ship_order.last_state)

Output:

orders shipped: 3
last state: NY

Set the attribute before the first call, or += 1 raises AttributeError. I use this for small counters, not core data.

Keeping a value alive across calls is the main idea behind static variables in Python functions.

How does a closure keep an inner function’s variable alive?

A closure is an inner function that remembers variables from the function that created it. The outer call has finished, yet the inner function still uses its rate:

def make_tip_calculator(rate):
    def tip(bill):
        return round(bill * rate, 2)   # 'rate' comes from the enclosing call
    return tip

tip_18 = make_tip_calculator(0.18)
tip_20 = make_tip_calculator(0.20)
print(f"18% tip on $62.40: ${tip_18(62.40):.2f}")
print(f"20% tip on $62.40: ${tip_20(62.40):.2f}")

# peek at the captured variable from outside
print(tip_18.__code__.co_freevars, tip_18.__closure__[0].cell_contents)

Output:

18% tip on $62.40: $11.23
20% tip on $62.40: $12.48
('rate',) 0.18
Command Prompt output of Python closures that calculate an 18 and 20 percent tip and show the captured rate
Each tip function keeps its own rate, and __closure__ shows the captured value from outside.

The last line shows the value is stored on the function. Peek at cell_contents when you debug, but just call the function in real code.

New to inner functions? See calling a function within a function in Python.

Keep state on a class instance and read it from outside

When several values belong together, use a class. Methods write to self, and you read those attributes with a dot:

class Register:
    def __init__(self, store):
        self.store = store
        self.sales = []            # instance state, reachable from outside

    def ring_up(self, amount):
        self.sales.append(amount)
        self.total = round(sum(self.sales), 2)

reg = Register("Austin #12")
reg.ring_up(24.99)
reg.ring_up(8.75)
print(reg.store, "sales:", reg.sales)
print(f"total: ${reg.total:.2f}")

Output:

Austin #12 sales: [24.99, 8.75]
total: $33.74
Command Prompt output of a Python class whose instance attributes store sales and a running total
The sales list and the total set inside ring_up() are read from outside through reg.

The __init__ method sets the starting state; Python class constructors with parameters explains it step by step.

Access a function’s variables from another file through module attributes

Top-level names in a module are attributes of that module, so other files can read what a function stored there:

# inventory.py
stock = {}

def receive(item, qty):
    stock[item] = stock.get(item, 0) + qty
    receive.last_item = item
import inventory

inventory.receive("coffee beans", 40)
inventory.receive("oat milk", 24)
print("stock:", inventory.stock)              # module attribute
print("last item:", inventory.receive.last_item)

Output:

stock: {'coffee beans': 40, 'oat milk': 24}
last item: oat milk

You’ll notice receive() didn’t need global: it changes the dict’s contents and sets an attribute, and neither rebinds a name.

For the import side, see calling a function from another file in Python.

When to use the Python global keyword instead

If your function must assign a new value to a module-level name, write global name first, or Python treats it as local.

Rebinding, nonlocal and a shared config module are covered in setting global variables in Python functions, and the error you get without it is explained in UnboundLocalError: local variable referenced before assignment.

Which way to get a variable out of a Python function?

ApproachUse it whenRead it with
returnYou need the result once (default choice)x = func()
Function attributeSmall counter or debug valuefunc.count
ClosureA configured helper functionhelper(arg)
Class instanceSeveral related values change over timeobj.total
Module attributeData shared between filesmodule.stock
globalRebinding a module-level namename

A few more posts on functions worth opening next:

Frequently asked questions

How do I use a variable from a function outside of it in Python?

Return it with return and assign the call to a variable, like total = get_total().

Why do I get NameError when I print a function’s variable?

It’s local, so it only exists while the function runs, so the name isn’t defined after the call.

How do I use a variable from one function in another function?

Return it from the first function and pass it as an argument to the second, or keep both functions as methods on one class.

Can I access a local variable without returning it?

You can’t once the call ends. Store it on the function, an object or a module instead, or return it.

Is using global variables bad practice in Python?

Not always, but they hide state and make testing harder. Prefer return values or a class, and keep global for small scripts.

Where are Python scopes documented?

See Python scopes and namespaces in the official tutorial.