Python decorator workshops

Back to Workshops

Guided JupyterLab workshops that teach Python decorators: what they do, how to write them, and why they work. Standard library only, and they run in the browser.

Launch the workshops

Each option opens the whole collection in a new window, where JupyterLab shows the workshops in the order to take them.

  • In browser runs Python inside your browser with JupyterLite. Nothing to install and no account needed. Your work is kept in your browser's storage.
  • Binder is a free public service needing no account. Sessions are temporary and can take a minute or two to start.
  • Codespaces needs a GitHub account and uses your Codespaces allowance. A codespace is kept until you delete it.
14 workshops About 3h 30m python decorators
1 What a decorator does 10m

Meet decorators as a user before writing one. Put three decorators from the standard library to work, watch each change what a function or a class does, and find out what the @ line actually means.

functools
2 Your first decorator 20m

Write the thing that goes after the @. Wrap a function by hand, then with the @ syntax, then build a timer, a call counter, and decorators that act before, after and instead of the function they wrap.

3 How a decorator remembers 15m

Find out how a wrapper still knows the function it wraps after the decorator has returned. Open a closure and look inside it, build functions that make functions, keep state with nonlocal, and meet the pitfall that catches everyone once.

closures
4 Decorators that take arguments 15m

Make a decorator work on any function, then make it configurable. Forward arguments with *args and **kwargs, add the extra layer that @repeat(3) needs, build a retry worth keeping, and handle a decorator used with and without parentheses.

5 Preserving the wrapped function 10m

Find out what a wrapper costs you, then fix it with one line. See what functools.wraps copies, why inspect still finds the original signature, and what is genuinely left over.

functools inspect
6 Stacking decorators 15m

Put more than one decorator on a function and find out that they are applied in one order and run in another. See a stack where the order changes the answer, and walk the chain back to the original function.

functools
7 Decorating methods 15m

Put a decorator on a method and meet the most common surprise in Python decorators. See which kinds work, find the instance hiding in args, write a decorator that uses it, and learn the real rule for stacking with staticmethod and classmethod.

classes
8 Decorators that are classes 15m

Write a decorator as a class rather than a function. Keep state in an instance attribute, restore the identity it quietly replaces, use the constructor in place of the extra layer a configurable decorator needs, and see what it still cannot do.

classes functools
9 How methods bind 20m

Find out how `obj.method()` finds its instance, by doing the binding by hand. Then fix the class-based decorator that could not do it, give a class its own `__get__`, and see that the protocol behind all of it is a plain language feature you can use directly.

descriptors methods
10 Decorating classes 15m

Put a decorator on a class rather than a function. Synthesise a `__repr__`, add comparison and meet the hashing trap that comes with it, freeze a class against assignment, and find out that `@dataclass` is an ordinary decorator doing exactly what you have just done by hand.

classes dataclasses
11 Caching results 15m

Build the decorator you met in the first workshop. Write a naive cache, break it twice, fix the key with signature.bind, then use the standard library's own and find out what unbounded caching costs.

functools caching
12 Registering functions 15m

Write a decorator that wraps nothing and changes nothing. Build a command registry, a route table and an event system, and recognise the shape you have already used in Flask, Click and pytest.

patterns
13 Retrying and handling errors 15m

Decorate the error path. Log a failure without swallowing it, translate an exception while keeping its cause, retry only the failures worth retrying, and watch the stacking order decide what ends up in your logs.

logging exceptions
14 Decorating async functions 15m

Put an ordinary decorator on an async def and watch it fail without saying so. Write a wrapper that awaits, one decorator that serves both kinds, and find out what happens when a wrapper blocks the event loop.

asyncio