Decorators from scratch

P29.decorators.01 · Audience: guest, it-ml, language-pro · Prerequisites: Closures & first-class functions

Real LLM grading for this pageLLM grading (this page):

A decorator looks like magic syntax, but it is nothing more than the closure machinery you just built, pointed at a function. This module strips the @ sign down to what actually runs, then rebuilds the two classics — a call counter and a memoiser — from scratch.

Step 1 / 3The wrap-and-return mental model
ⓘ Concept: @a is just f = a(f)
@count_calls above def greet(...) is executed once, at definition time, as greet = count_calls(greet). The decorator receives the function object and returns a replacement — usually an inner wrapper that does something extra and then calls the original. Define, wrap, return: that is the whole trick.

Why it matters — Once you read the @ sign as plain assignment, every decorator — logging, caching, retrying, auth — is the same three-line shape, and none of it is magic.

Ask the mentor about this module

Ask a question about this content. The mentor explains and grounds its answer in what you are studying; asking is recorded as a learning signal, not a grade.

Ctrl/Cmd + Enter to send

🎓 Practice ladder

2 graded rungs · ~20 min

Your turn: write @count_calls with functools.wraps, then rebuild @memoize — the hand-rolled heart of lru_cache.

Rung 1 — write @count_calls from scratch

Loading exercise…

Rung 2 — rebuild @memoize by hand

Loading exercise…

By the end, @anything should read as ordinary code to you: a function call at definition time that swaps in a wrapper you could have written yourself.