01 / 08

Why is it important to use functools.wraps when writing a decorator?

Difficulty: 8/10
Decorators, Functools, Introspection

functools.wraps preserves identity and metadata so introspection tools keep working

Without functools.wraps, the object bound to the decorated name is the wrapper, so name, doc, module, qualname, and dict all describe the wrapper instead of the original function. That breaks documentation generators, debuggers, tracebacks, logging, and frameworks that read function attributes at import time. functools.wraps copies those attributes from the wrapped function onto the wrapper and, since Python 3.2, sets wrapped so tools like inspect.signature and inspect.unwrap can follow the chain back to the original. It is essentially functools.update_wrapper with sensible defaults.

  1. 1

    functools.WRAPPER_ASSIGNMENTS covers module, name, qualname, annotations, and doc.

  2. 2

    It also updates dict and sets wrapped, which inspect.signature follows by default.

  3. 3

    Trade-off: wraps makes the wrapper masquerade as the original. That is usually what you want, but it can hide instrumentation from tools that explicitly unwrap.

  4. 4

    Common mistake: manually assigning only wrapper.name = fn.name and thinking that is enough. Signature, annotations, and docstring still lie.

  5. 5

    Common mistake: assuming wraps changes the actual call signature. It only changes metadata; if a tool enforces the real signature you need a signature-preserving wrapper.

  6. 6

    Version note: wrapped and the automatic assignment in functools.wraps were added in Python 3.2. functools.WRAPPER_ASSIGNMENTS is a stable public constant you can customize.

javascript

Scenario Questions

0-2 years experience

  1. 1Why does a decorated function lose its docstring and name if you do not use functools.wraps?
  2. 2Which attributes does functools.wraps copy onto the wrapper?

2-5 years experience

  1. 1A web framework reads route metadata from function attributes. Why does wrapping break it and how does wraps fix it?
  2. 2How do you get from a decorated function back to the original implementation at runtime?

5-8 years experience

  1. 1A signature-based tool rejects your decorated function with an unexpected-keyword error even though wraps is applied. How do you diagnose and fix it?
  2. 2You deliberately want the wrapper to expose a different signature than the wrapped function. What are the risks and how do you document them?

8+ years experience

  1. 1Design a decorator that preserves runtime introspection, IDE autocomplete, and static typing for the wrapped function across a large codebase.
  2. 2How does __wrapped__ affect debuggers and profilers, and in what situations would you intentionally break the chain?

Follow-up Questions

  • What does inspect.signature do with __wrapped__, and how do you inspect the real wrapper signature instead?
  • When would hiding the wrapper behind wraps actually be harmful?
Share

Share via WhatsApp, X, Facebook, LinkedIn or copy link. Open Graph preview enabled.