To pass a function as a parameter in Python, write its name without parentheses, like checkout(59.99, add_sales_tax). The receiving function stores it in a parameter and calls it whenever it’s ready. Functions are plain objects, so no special syntax is needed:
def checkout(price, rule):
return rule(price)
checkout(59.99, add_sales_tax) # no () after add_sales_tax
I tested this page on Python 3.12.5 from a Windows Command Prompt; each output block is pasted straight from that session.
We’ll cover callbacks, key=, lambdas, functools.partial, argument forwarding and type hints.
How do you pass a function as a parameter in Python?
Two price rules, one checkout() that accepts either, and the classic mistake at the end:
def add_sales_tax(price):
return round(price * 1.0825, 2)
def apply_coupon(price):
return round(price - 10, 2)
def checkout(price, rule):
return rule(price) # call whatever function was passed in
print(checkout(59.99, add_sales_tax))
print(checkout(59.99, apply_coupon))
try:
checkout(59.99, add_sales_tax(59.99)) # called too early: passes a float
except TypeError as err:
print("TypeError:", err)
Output:
64.94
49.99
TypeError: 'float' object is not callable

With parentheses, Python passes the float result, which can’t be called. If defining functions is still new to you, start with how to define a function in Python.
Pass a callback function to run later
A callback is a function another function calls when something happens. This shipping routine just calls whatever you passed:
def ship_orders(orders, on_shipped, on_failed):
for order_id, state in orders:
if state in {"TX", "CA", "NY"}:
on_shipped(order_id)
else:
on_failed(order_id, f"no warehouse serves {state}")
def email_customer(order_id):
print(f"Order {order_id}: shipping email sent")
def log_problem(order_id, reason):
print(f"Order {order_id}: FAILED - {reason}")
ship_orders([(1001, "TX"), (1002, "AK"), (1003, "NY")], email_customer, log_problem)
Output:
Order 1001: shipping email sent
Order 1002: FAILED - no warehouse serves AK
Order 1003: shipping email sent

Swap in a Slack message; ship_orders() never changes. If you need to pick the function from a string, such as a menu choice, see calling a function by its string name in Python.
Pass a function to key= in sorted(), max() and min()
Every key= argument is a passed function: Python calls it once per item and compares the results. That’s how many Python built-in functions let you customize their behavior:
customers = [("Olivia", 1250.50), ("james", 980.00), ("Emma", 2310.75)]
def total_spent(customer):
return customer[1]
print(max(customers, key=total_spent))
names = [name for name, _ in customers]
print(sorted(names)) # uppercase sorts before lowercase
print(sorted(names, key=str.lower)) # a built-in method works as a key too
Output:
('Emma', 2310.75)
['Emma', 'Olivia', 'james']
['Emma', 'james', 'Olivia']
Pass a lambda function as an argument
When the function is a one-liner you’ll use once, a lambda saves you a named def. Lambdas are covered in depth in how to use lambda functions in Python:
prices = [19.99, 45.00, 120.50, 8.75]
print(list(map(lambda p: round(p * 0.9, 2), prices))) # 10% off
Output:
[17.99, 40.5, 108.45, 7.88]
map() takes the function first and the data second. My guide to the map() function in Python shows when a list comprehension reads better.
Pass a function with fixed arguments using functools.partial
map() calls its function with one argument, but add_sales_tax() needs two. functools.partial fixes the tax rate ahead of time and gives you a new one-argument callable:
from functools import partial
def add_sales_tax(price, rate):
return round(price * (1 + rate), 2)
texas = partial(add_sales_tax, rate=0.0625)
california = partial(add_sales_tax, rate=0.0725)
cart = [25.00, 99.99, 14.50]
print("TX:", list(map(texas, cart)))
print("CA:", list(map(california, cart)))
print(texas.func.__name__, texas.keywords)
Output:
TX: [26.56, 106.24, 15.41]
CA: [26.81, 107.24, 15.55]
add_sales_tax {'rate': 0.0625}

A lambda like lambda p: add_sales_tax(p, 0.0625) works too, but I prefer partial because it keeps .func and .keywords for debugging.
Forward arguments to the passed function with *args and **kwargs
Wrappers like loggers and retry helpers don’t know the arguments ahead of time. Collect them with *args and **kwargs, then unpack them into the call. The difference between *args and **kwargs explains both:
def run_logged(func, *args, **kwargs):
print(f"-> {func.__name__} args={args} kwargs={kwargs}")
result = func(*args, **kwargs)
print(f"<- {func.__name__} returned {result!r}")
return result
def book_flight(origin, destination, seats=1, cabin="economy"):
return f"{seats} {cabin} seat(s) {origin}->{destination}"
run_logged(book_flight, "JFK", "LAX")
run_logged(book_flight, "ORD", "SFO", seats=2, cabin="business")
Output:
-> book_flight args=('JFK', 'LAX') kwargs={}
<- book_flight returned '1 economy seat(s) JFK->LAX'
-> book_flight args=('ORD', 'SFO') kwargs={'seats': 2, 'cabin': 'business'}
<- book_flight returned '2 business seat(s) ORD->SFO'
Type hint a function parameter with Callable
Callable[[float], float] means “a function that takes one float and returns a float.” Python doesn’t enforce it, but mypy does. I ran mypy, then the script:
from collections.abc import Callable
def apply_rule(prices: list[float], rule: Callable[[float], float]) -> list[float]:
return [rule(p) for p in prices]
def half_off(price: float) -> float:
return round(price / 2, 2)
def label(price: float) -> str:
return f"${price:.2f}"
print(apply_rule([40.00, 15.50], half_off))
print(apply_rule([40.00, 15.50], label)) # wrong kind of function
Output:
price_rules.py:13: error: Argument 2 to "apply_rule" has incompatible type "Callable[[float], str]"; expected "Callable[[float], float]" [arg-type]
Found 1 error in 1 file (checked 1 source file)
[20.0, 7.75]
['$40.00', '$15.50']

So hints catch the bug in your editor or CI, not at runtime. To check for a callable while the program runs, use the Python callable() function.
These related tutorials build on it:
- Get the name of a function in Python
- Return a function in Python
- The reduce() function in Python
- Call a function from another file in Python
Frequently asked questions
How do I pass a function as an argument in Python?
Use its name without parentheses, like checkout(59.99, add_sales_tax), then call the parameter inside.
Why do I get “object is not callable” when passing a function?
You added parentheses, so Python passed the return value instead of the function.
How do I pass a function that needs its own arguments?
Forward them with *args and **kwargs, or bind them with functools.partial or a lambda.
What is a callback function in Python?
A function you pass to another function, which calls it later, such as when an order ships.
How do I type hint a function parameter?
Use Callable[[ArgTypes], ReturnType] from collections.abc, such as Callable[[float], float].
Where is functools.partial documented?
See functools.partial() in the Python docs.

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