What are decorators and how do they work?medium

Type
conceptual
Topic
decorators
Frequency
common
Tags
decorators, higher-order functions, closures, functools
Answer

A decorator wraps a function to add behaviour without modifying its body. Functions are first-class objects, so a decorator takes a function, defines a wrapper that adds logic, and returns the wrapper. The @syntax is shorthand for fn = decorator(fn).

Explanation

The foundation is that Python functions are objects — assignable and passable as arguments. A closure is an inner function that remembers variables from its enclosing scope. Always use @functools.wraps(fn) inside your decorator to preserve __name__ and __doc__ — without it, debugging and stack traces break. For decorators with arguments like @retry(n=3), you need a triple-nested pattern: a function receiving arguments that returns the actual decorator. Stacked decorators apply bottom-up: @a @b def f means a(b(f)), so @b wraps first.

Follow-upHow do decorators with arguments work?
Follow-upWhat does @functools.wraps do and why is it needed?
Follow-upIf you stack @a and @b above a function, which wraps first?