Question presented to candidate:
"Most decorator examples put @functools.wraps(func) on the inner wrapper. What goes wrong if you leave it out, and what exactly does wraps do?"
What a strong answer should cover:
- Without it, the decorated name points at the wrapper, so
__name__,__qualname__,__doc__,__module__and annotations describe the wrapper, not the original. - What breaks: logs and tracebacks that print names,
help()and docs,inspect.signature, registries keyed by__name__, andpickle, which finds functions by module and qualified name. - What
wrapsdoes: it isfunctools.update_wrapperas a decorator; it copiesWRAPPER_ASSIGNMENTS, mergesWRAPPER_UPDATES(__dict__) and sets__wrapped__to the original. __wrapped__letsinspect.signaturereport the real signature and letsinspect.unwrapor tests reach the undecorated function.- What it does not do: it does not change the wrapper code, defaults or behaviour; it only copies metadata. A version detail: 3.12 added
__type_params__to the copied attributes.
Code / implementation expected: Yes β a decorator with and without wraps, printing __name__, __doc__ and the signature.