How to Call a Function Within a Function in Python

To call a function within a function in Python, write its name with parentheses inside the other function’s body, like subtotal(prices). Python looks the name up when the outer function runs, not when it’s defined:

def order_total(prices):
    return subtotal(prices) + sales_tax(subtotal(prices))

Each listing below was run on Python 3.12.5; the Command Prompt captures are from those same runs, and the numbers are USD shopping-cart totals.

You’ll see helper functions, why definition order sometimes matters, inner (nested) functions, closures with nonlocal, and passing a function to another function.

Call a function inside another function

Splitting work into small functions and calling them from a bigger one is the most common case. order_total() calls two helpers:

TAX_RATE = 0.0825                         # Austin, TX

def subtotal(prices):
    return sum(prices)

def sales_tax(amount):
    return round(amount * TAX_RATE, 2)

def order_total(prices):
    base = subtotal(prices)               # call one function inside another
    tax = sales_tax(base)
    return base + tax

cart = [19.99, 5.25, 102.00]
print(f"Subtotal: ${subtotal(cart):,.2f}")
print(f"Tax:      ${sales_tax(subtotal(cart)):,.2f}")
print(f"Total:    ${order_total(cart):,.2f}")

Output:

Subtotal: $127.24
Tax:      $10.50
Total:    $137.74
Command Prompt output of a Python order_total function that calls subtotal and sales_tax helper functions
The subtotal, the Texas sales tax and the order total, all printed in dollars from the helper calls.

The helper’s return value is what the caller gets back, so each one must return rather than print. My guide to the return statement in Python goes deeper on that.

Does a Python function have to be defined before you call it?

Only before the call actually runs. Inside a function body, a later function is fine. At module level, calling a function above its def line fails:

def checkout(prices):
    return format_usd(sum(prices))        # format_usd isn't defined yet - that's fine here

def format_usd(amount):
    return f"${amount:,.2f}"

print(checkout([1250.00, 49.50]))         # works: format_usd exists by the time checkout runs

print(ship_label("Denver"))               # fails: ship_label is called before its def line runs

def ship_label(city):
    return f"Ship to {city}"

Output:

$1,299.50
Traceback (most recent call last):
  File "C:\pyguides\define_order.py", line 9, in <module>
    print(ship_label("Denver"))               # fails: ship_label is called before its def line runs
          ^^^^^^^^^^
NameError: name 'ship_label' is not defined
Command Prompt output of Python calling a function defined later inside another function, then a NameError at module level
The checkout total prints, then the call to ship_label raises a NameError because its def hasn’t run yet.

So the order of def blocks in a file rarely matters, but top-level calls belong below them. This is also why many scripts end with a main() call. Name lookup rules are covered in Python variable scope.

Define and call a nested function in Python

You can also define a function inside another one. The inner function is created each time the outer one runs, and it’s invisible outside it:

def invoice_lines(items):
    def line(name, qty, price):           # inner function: only exists inside invoice_lines
        return f"{name:<12}{qty:>3} x ${price:>9,.2f} = ${qty * price:>9,.2f}"

    for name, qty, price in items:
        print(line(name, qty, price))

invoice_lines([("Keyboard", 2, 49.99), ("Monitor", 1, 1249.00), ("USB cable", 5, 8.75)])

try:
    line("Mouse", 1, 25.00)
except NameError as err:
    print("NameError:", err)

Output:

Keyboard      2 x $    49.99 = $    99.98
Monitor       1 x $ 1,249.00 = $ 1,249.00
USB cable     5 x $     8.75 = $    43.75
NameError: name 'line' is not defined
Command Prompt output of a Python inner function formatting invoice lines, then NameError when called outside
Three invoice lines in USD print from the inner function, and calling line() from outside raises NameError.

I use inner functions for one-off helpers. If a helper is useful elsewhere, keep it at module level so you can test it. An inner function’s local names follow the rules in accessing variables outside a function.

Return an inner function as a closure

An inner function can use the outer function’s arguments even after the outer function has returned. That pairing is a closure:

def make_tax_calculator(rate):
    def add_tax(amount):
        return round(amount * (1 + rate), 2)   # uses rate from the outer function
    return add_tax

texas = make_tax_calculator(0.0825)
oregon = make_tax_calculator(0.0)

print(texas(100.00), oregon(100.00))
print(texas.__name__, texas.__closure__[0].cell_contents)

Output:

108.25 100.0
add_tax 0.0825

Each call to make_tax_calculator() builds a new add_tax that remembers its own rate. Decorators are built on exactly this, as you’ll see in Python decorator examples.

Change an outer variable from a nested function with nonlocal

Reading an outer variable just works. Assigning to it makes Python treat it as a new local, unless you declare it nonlocal:

def running_total():
    total = 0.0
    def add(amount):
        nonlocal total                     # without this line: UnboundLocalError
        total += amount
        return total
    return add

register = running_total()
for sale in (12.50, 7.25, 30.00):
    print(f"${register(sale):,.2f}")

Output:

$12.50
$19.75
$49.75

Drop the nonlocal line and the first total += amount fails. That error and its fixes are in UnboundLocalError: local variable referenced before assignment.

Pass a function to another function and call it there

Functions are objects, so you can pass one in and let the other function decide when to call it. Pass the name without parentheses:

def apply_discount(price):
    return round(price * 0.9, 2)

def add_shipping(price):
    return round(price + 7.99, 2)

def process(prices, step):
    return [step(p) for p in prices]       # call whatever function was passed in

prices = [20.00, 45.50, 100.00]
print(process(prices, apply_discount))
print(process(prices, add_shipping))
print(process(prices, lambda p: round(p * 1.0825, 2)))

print(process(prices, apply_discount()))   # mistake: calling it instead of passing it

Output:

[18.0, 40.95, 90.0]
[27.99, 53.49, 107.99]
[21.65, 49.25, 108.25]
Traceback (most recent call last):
  File "C:\pyguides\pass_function.py", line 15, in <module>
    print(process(prices, apply_discount()))   # mistake: calling it instead of passing it
                          ^^^^^^^^^^^^^^^^
TypeError: apply_discount() missing 1 required positional argument: 'price'
Command Prompt output of Python passing functions and a lambda as arguments, then a TypeError from calling the function instead of passing it
Discount, shipping and lambda results print as lists; adding parentheses calls apply_discount with no price and raises TypeError.

With apply_discount(), Python calls it on the spot with no price. To check whether something can be called before you call it, see the callable() function. A function that calls itself is a different pattern, covered in recursion in Python.

Calling a function within a function: quick reference

PatternWhat it looks likeUse it for
Helper callbase = subtotal(prices)Splitting work into small functions
Inner functiondef line(...) inside another defHelpers used in one place only
Closurereturn add_taxFunctions that remember settings
nonlocalnonlocal totalUpdating an outer variable
Function as argumentprocess(prices, apply_discount)Callbacks and pluggable steps

These function guides pair well with this one:

Frequently asked questions

How do you call a function inside another function in Python?

Write its name with parentheses and arguments inside the other function’s body, for example tax = sales_tax(base).

Can I call a function before it is defined in Python?

Inside another function, yes, as long as the definition has run before that function is called. At module level, no: you get a NameError.

Can I call a nested function from outside?

Not directly. Return it from the outer function, or move it to module level.

What is the difference between a nested function and a closure?

A closure is a nested function that uses variables from the enclosing function and keeps them after that function returns.

Why do I get TypeError: missing 1 required positional argument when passing a function?

You added parentheses, so Python called it right away. Pass apply_discount, not apply_discount().

Where does Python document how names are looked up in functions?

See resolution of names in the Python reference.