Practice & Assessment
Test your understanding of Functions and Functional Patterns
Multiple Choice Questions
5What is the output of calling `broken()` twice, where `broken` uses a mutable default `items=[]` and appends 1 each call?
What does `*args` collect inside a function?
What does `nonlocal` do in Python?
What is the correct argument order in a Python function signature?
Why should you use `@functools.wraps(func)` in a decorator?
Coding Challenges
1Timing decorator
Write a decorator called `timer` that measures and prints the execution time of any function it decorates. Use `time.perf_counter()` for measurement. The decorator must preserve the original function's name and return value. Test it on a function that sums numbers in a range. Input: any callable. Output: prints 'func_name ran in X.XXXXXX seconds', returns original result. Estimated time: 20-25 minutes.
Mini Project
Configurable Pipeline Runner
Build a data transformation pipeline using closures and decorators. Create a `Pipeline` class (or factory function) that accepts a list of transformation functions. Each step receives the output of the previous step. Add a `@log_step` decorator that prints the step name and output at each stage. Include a `@validate` decorator that checks the output is not None or empty before passing it forward. Test the pipeline with string transformations: strip whitespace, convert to lowercase, split into words, filter short words. All concepts from the module โ closures, *args/**kwargs, lambdas, decorators, and functools.wraps โ must appear in the solution.
