Python Decorators: A Comprehensive Exam
This exam assesses your understanding and practical application of Python decorators. It consists of a single comprehensive question divided into five parts, requiring both conceptual explanations and practical code implementation. Please address each part thoroughly.
Part 1: Explain Higher-Order Functions (Conceptual):
Provide a clear definition of higher-order functions in Python. Explain the characteristics that make a function 'higher-order' and provide a simple, illustrative Python code example of a higher-order function.
Part 2: Implement @log
Decorator (Practical):
Implement a Python decorator named @log
. This decorator should, when applied to a function, perform the following actions:
- Before the decorated function executes, print a log message indicating the function's name and all the arguments it received (positional and keyword arguments).
- After the decorated function executes, print a log message indicating the function's name and its return value.
- The log messages should be descriptive and clearly formatted (e.g., 'Calling function_name with args (...) and kwargs {...}', 'function_name returned ...').
Part 3: Implement @timeit
Decorator (Practical):
Implement a Python decorator named @timeit
. This decorator should, when applied to a function, measure the total execution time of the decorated function. After the function completes, it should print the execution time to the console in a user-friendly format (e.g., 'Function 'function_name' executed in X.XXX seconds'). Ensure precision up to at least three decimal places.
Part 4: Demonstrate Usage (Application):
Create two distinct Python functions:
calculate_factorial(n)
: A function that calculates the factorial of a given numbern
.simulate_work(seconds)
: A function that takes a number of seconds and simulates work by pausing execution for that duration (e.g., usingtime.sleep
).
Apply both the @log
and @timeit
decorators to each of these functions. Then, show example calls for both decorated functions, demonstrating how the decorators' outputs are displayed.
Part 5: Discuss Benefits (Conceptual):
Explain the key advantages of using decorators for adding cross-cutting concerns like logging and timing, compared to manually adding the same boilerplate code within each function. Discuss concepts like code reusability, separation of concerns, and maintainability.