Functions as Arguments in Python 2026
Passing functions as arguments to other functions is one of the most powerful and commonly used patterns in Python. It enables higher-order functions, callbacks, decorators, strategy patterns, and much more flexible code.
TL;DR — Key Takeaways 2026
- You can pass any function as an argument just like any other object
- This pattern is the foundation of callbacks, event handlers, and strategy design
- Use
Callablefromtypingfor clear type hints - Keep passed functions pure when possible for predictable behavior
1. Basic Example
def greet(name: str) -> str:
return f"Hello, {name}!"
def shout(text: str) -> str:
return text.upper() + "!!!"
def process_message(message: str, formatter):
"""formatter is a function passed as argument."""
formatted = formatter(message)
print(formatted)
process_message("hello world", greet) # Hello, hello world
process_message("hello world", shout) # HELLO WORLD!!!
2. Real-World Higher-Order Function
from typing import Callable, List
def apply_to_all(items: List[int], operation: Callable[[int], int]) -> List[int]:
"""Apply any function to every item in the list."""
return [operation(item) for item in items]
def square(x: int) -> int:
return x * x
def double(x: int) -> int:
return x * 2
numbers = [1, 2, 3, 4, 5]
print(apply_to_all(numbers, square)) # [1, 4, 9, 16, 25]
print(apply_to_all(numbers, double)) # [2, 4, 6, 8, 10]
3. Best Practices in 2026
- Use descriptive parameter names (e.g.,
processor,formatter,callback) - Add proper type hints with
Callable[[ArgTypes], ReturnType] - Document what arguments the passed function should accept and what it should return
- Prefer small, focused functions when passing them as arguments
- Combine with lists or dictionaries of functions for even more flexibility
Higher-Order Functions in Data Work
A function that takes another function as an argument is called a higher-order function. Python's built-ins map, filter, sorted, min and max are examples, and pandas offers many more, such as Series.apply, DataFrame.agg and groupby().transform.
Passing a function lets the caller decide the behaviour while the higher-order function handles the structure, such as looping, grouping or error handling. This separates what to do from how to repeat it.
When writing your own, document what the function argument must accept and return. A type hint such as Callable[[float], float] makes the contract clear and lets type checkers catch mistakes.
Prefer named functions over long lambdas, because named functions have readable tracebacks and can be tested on their own.
Worked Example: A Retry Helper That Takes a Function
We write a helper that calls any function and retries it when it raises a specific error.
from typing import Callable
def retry(func: Callable[[], float], attempts: int = 3) -> float:
for n in range(1, attempts + 1):
try:
return func()
except ValueError as e:
print(f"attempt {n} failed: {e}")
raise RuntimeError("all attempts failed")
readings = iter(["n/a", "bad", "21.5"])
def read_sensor() -> float:
return float(next(readings))
print(retry(read_sensor))
The first two readings cannot be converted, so two attempts fail with a ValueError message. The third returns 21.5. The retry logic knows nothing about sensors, so it can be reused for any function that may raise ValueError.
Practical Tips
When a pandas method accepts a function, check whether a built-in vectorised method does the same job. Methods like .str.lower() or .sum() are much faster than apply with a Python function, because they run in optimised code.
Keep the passed function free of side effects where possible. A function that only computes a result can be reused, tested and run in parallel safely.
Name parameters that take functions clearly, such as transform or on_error, so callers know what to pass.
Return values rather than printing inside passed functions, so results stay reusable.
Common Mistakes
- Passing func() instead of func.
- Catching every exception and hiding real bugs.
- Long lambdas that are hard to read and test.
- Not documenting what the passed function must return.
Quick Summary
- Higher-order functions take functions as arguments.
- They separate behaviour from structure.
- Use Callable hints to document the contract.
- Prefer named functions to long lambdas.
Conclusion
Passing functions as arguments is a cornerstone of modern Python programming. In 2026, this technique allows you to write highly reusable, modular, and extensible code. From simple data processing to complex event-driven systems, functions as arguments unlock powerful design patterns.
Next steps:
- Look for repetitive code that can be replaced by passing different functions as arguments