Module 11: Functions in depth
*args and **kwargs, functions as objects, closures and decorators: the tools behind clean Python.
- Flexible arguments: *args, **kwargs and the default trap: args collects extra values into a tuple, kwargs into a dict; never use a mutable default, use None and create it inside.
- Functions are objects: lambda and closures: Functions are objects you can pass and return; a closure remembers outer variables (change them with nonlocal) and looks them up at call time.
- Decorators I: what @ really does: @d above def f means f = d(f); the wrapper takes args, kwargs, returns the result, and uses @wraps(fn); stacked decorators apply bottom-up and run top-down.
- Decorators II: arguments, classes and built-ins: A decorator with settings is a factory: @retry(3) means f = retry(3)(f); a class with call can decorate; @lrucache needs hashable arguments; @property is just a decorator.
Ends with a 13-question checkpoint (80% passes) and a mini project: Canteen Counter: a decorator toolkit.