Higher-order functions are functions that can take other functions as arguments or return them as results. Decorators are a form of higher-order function that allow you to add behavior to existing functions.
Here’s a complete example that demonstrates the use of higher-order functions, decorators, and their application on recursive functions:
import time
# Decorator to measure execution time
def timing_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"Function '{func.__name__}' executed in {end_time - start_time:.6f} seconds")
return result
return wrapper
# Decorator to log function calls
def logging_decorator(func):
def wrapper(*args, **kwargs):
print(f"Calling function '{func.__name__}' with arguments {args} and {kwargs}")
result = func(*args, **kwargs)
print(f"Function '{func.__name__}' returned {result}")
return result
return wrapper
# Applying multiple decorators
@timing_decorator
@logging_decorator
def factorial(n):
"""Recursively calculate the factorial of n."""
if n == 0:
return 1
else:
return n * factorial(n - 1)
@timing_decorator
@logging_decorator
def fibonacci(n):
"""Recursively calculate the nth Fibonacci number."""
if n <= 0:
return 0
elif n == 1:
return 1
else:
return fibonacci(n - 1) + fibonacci(n - 2)
# Test the decorated functions
print(f"Factorial of 5: {factorial(5)}")
print(f"Fibonacci of 10: {fibonacci(10)}")
factorial
and fibonacci
functions are decorated with both timing_decorator
and logging_decorator
.logging_decorator
wraps the function first, followed by the timing_decorator
.n
recursively.n
is 0, it returns 1 (base case).n
multiplied by the factorial of n-1
.n
is less than or equal to 0, it returns 0 (base case for non-positive integers).n
is 1, it returns 1 (base case).n-1
and n-2
.factorial
function is tested with the input 5.fibonacci
function is tested with the input 10.When you run the above code, you will get output similar to the following:
Calling function 'factorial' with arguments (5,) and {}
Calling function 'factorial' with arguments (4,) and {}
Calling function 'factorial' with arguments (3,) and {}
Calling function 'factorial' with arguments (2,) and {}
Calling function 'factorial' with arguments (1,) and {}
Calling function 'factorial' with arguments (0,) and {}
Function 'factorial' returned 1
Function 'factorial' returned 1
Function 'factorial' returned 2
Function 'factorial' returned 6
Function 'factorial' returned 24
Function 'factorial' returned 120
Function 'factorial' executed in 0.000021 seconds
Factorial of 5: 120
Calling function 'fibonacci' with arguments (10,) and {}
Calling function 'fibonacci' with arguments (9,) and {}
...
Function 'fibonacci' executed in 0.005631 seconds
Fibonacci of 10: 55
This output shows the logging and timing information for each call to the factorial
and fibonacci
functions, demonstrating the combined effects of the decorators.