All concepts

Decorators

Wrap a function to add behavior—logging, timing, auth—without touching its code.

Python · Intermediate · ~5 min

In plain English

A wrapper you put around a function so that something happens every time it runs — timing it, retrying it, logging it — without editing the function itself.

Why it's worth your time

Every framework you'll touch is built on them, and 'explain a decorator' is a standard screening question.

If you remember three things

  • @decorator is just func = decorator(func)
  • Use functools.wraps or you destroy the function's name and docstring
  • A decorator with arguments needs one more layer of nesting

Overview

A decorator is a function that takes another function, wraps it in a new function that runs extra behavior before or after the call, and returns that wrapper. The @decorator syntax is just sugar for f = decorator(f). functools.wraps copies the original's metadata so introspection still works.

In an interview

A decorator is a higher-order function: it receives a function and returns a replacement that adds behavior around it—logging, timing, auth, caching, retries—without editing the original. The @ syntax simply rebinds the name to the decorated version. I always add functools.wraps so the wrapper keeps the original name, docstring, and signature.

Production defaults

Always
@functools.wraps(fn) on the inner function. Without it, introspection, docs and debuggers all break
Signature
def wrapper(*args, **kwargs) so you don't constrain what you wrap
Common uses
retry, timing, caching (functools.lru_cache), auth checks, registration

What breaks

  • Decorated function shows the wrapper's name — Missing functools.wraps. It copies __name__, __doc__ and __wrapped__ across.
  • Decorator runs once instead of per call — You put the logic in the outer function instead of the inner wrapper.

Watch it explained

25. Decorators [Python 3 Programming Tutorials] — codebasics, 9:07

Related