Python tutorials > Core Python Fundamentals > Functions > What are higher-order functions?
What are higher-order functions?
Higher-order functions are a powerful feature in Python that allow you to treat functions as first-class citizens. This means you can pass functions as arguments to other functions, return functions from functions, and assign functions to variables. This capability enables you to write more flexible, reusable, and concise code.
Definition and Core Concept
A higher-order function is a function that does at least one of the following: This contrasts with first-order functions, which do not accept functions as arguments or return them.
Example: Function as Argument
In this example, operate
is a higher-order function. It takes a function func
as an argument, along with two numbers x
and y
. It then calls func
with x
and y
and returns the result. The add
and subtract
functions are passed as arguments to operate
.
def operate(func, x, y):
return func(x, y)
def add(x, y):
return x + y
def subtract(x, y):
return x - y
result_addition = operate(add, 5, 3)
print(f"Addition result: {result_addition}") # Output: Addition result: 8
result_subtraction = operate(subtract, 5, 3)
print(f"Subtraction result: {result_subtraction}") # Output: Subtraction result: 2
Example: Function as Return Value
Here, create_multiplier
is a higher-order function that returns another function, multiplier
. The multiplier
function is a closure; it remembers the value of factor
from the enclosing scope of create_multiplier
. This allows us to create specialized functions like double
and triple
.
def create_multiplier(factor):
def multiplier(x):
return x * factor
return multiplier
double = create_multiplier(2)
triple = create_multiplier(3)
print(f"Double of 5: {double(5)}") # Output: Double of 5: 10
print(f"Triple of 5: {triple(5)}") # Output: Triple of 5: 15
Real-Life Use Case: Sorting with a Custom Key
Sorting a list of dictionaries based on a specific key is a common task. The sorted
function in Python accepts a key
argument, which is a function. This allows us to specify a custom sorting logic. In this case, we sort a list of student dictionaries based on their 'grade'.
students = [
{"name": "Alice", "grade": 85},
{"name": "Bob", "grade": 92},
{"name": "Charlie", "grade": 78}
]
# Sort students based on their grade
sorted_students = sorted(students, key=lambda student: student["grade"])
print(sorted_students)
Real-Life Use Case: Decorators
Decorators are a prime example of higher-order functions. The timer
function in this example is a decorator. It takes a function as an argument and returns a modified version of that function (the wrapper
). The wrapper
adds extra functionality (timing the execution) before and/or after calling the original function. The @timer
syntax is syntactic sugar for slow_function = timer(slow_function)
.
import time
def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
execution_time = end_time - start_time
print(f"Function {func.__name__} took {execution_time:.4f} seconds to execute.")
return result
return wrapper
@timer
def slow_function():
time.sleep(2)
slow_function()
Best Practices
Interview Tip
When discussing higher-order functions in an interview, be prepared to:
map
, filter
, reduce
, decorators).
When to Use Them
Higher-order functions are particularly useful in these scenarios:
map
, filter
, reduce
).
Memory Footprint
The memory footprint of higher-order functions themselves is generally small. However, consider the potential impact of the functions they operate on. If you're passing large datasets to a function within a higher-order function, the memory usage could be significant. Closures, which are often used with higher-order functions, can also retain references to variables in their enclosing scope, potentially increasing memory usage if those variables are large.
Alternatives
While higher-order functions offer a powerful way to abstract and reuse code, there are alternative approaches:
Pros
Cons
FAQ
-
What is the difference between a first-order and a higher-order function?
A first-order function does not take functions as arguments or return them. A higher-order function does at least one of those things.
-
Are lambda functions higher-order functions?
No, lambda functions are anonymous functions that can be passed as arguments to higher-order functions. They are not higher-order functions themselves.
-
Can higher-order functions improve code performance?
While the primary benefit is code organization and reusability, higher-order functions themselves don't inherently improve or worsen performance. Performance depends on the complexity of the functions being passed and the overall algorithm.