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

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

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

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'

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
| Pattern | What it looks like | Use it for |
|---|---|---|
| Helper call | base = subtotal(prices) | Splitting work into small functions |
| Inner function | def line(...) inside another def | Helpers used in one place only |
| Closure | return add_tax | Functions that remember settings |
nonlocal | nonlocal total | Updating an outer variable |
| Function as argument | process(prices, apply_discount) | Callbacks and pluggable steps |
These function guides pair well with this one:
- Pass a tuple as an argument to a function
- Return a tuple from a Python function
- Fix SyntaxError: ‘return’ outside function
- Call a super constructor in Python
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.

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