Ch. 9 · Python

Python Decorators and Function Metadata

Python Decorators and Function Metadata. Learn the reasoning, a practical example, common mistakes and an interview exercise.

~2 min readintermediateupdated Oct 3, 2026

A decorator wraps behavior around a callable. Preserve the public signature expectations, return values, exceptions and useful metadata.

Before you start

You should know Python functions, collections and exceptions. Use a small isolated script or interactive session to trace the example. Pay attention to when objects are created and when work executes; iteration, binding and mutation can happen at different points in a program.

The practical goal is to reason through this situation: A logging wrapper returns the underlying result and uses functools.wraps. Read the walkthrough first, then try the interview exercise before opening its answer. The important part is explaining the decision and its consequences, rather than remembering a definition alone.

Step-by-step walkthrough

Step 1: Preserve the call contract

Forward supported arguments and return the underlying function’s result.

Step 2: Keep metadata

Use functools.wraps so documentation and introspection retain useful identity.

Step 3: Match asynchronous execution

An async callable needs an async wrapper that awaits and propagates its outcome.

Worked scenario

A logging wrapper returns the underlying result and uses functools.wraps.

from functools import wraps
def logged(function):
    @wraps(function)
    def wrapper(*args, **kwargs):
        print('calling', function.__name__)
        return function(*args, **kwargs)
    return wrapper
python

This wrapper is for synchronous functions. Omitting return changes every successful result to None; async wrapping needs a separate awaited implementation.

Common mistake

Forgetting return causes callers to receive None despite successful work.

Verify the behavior

Check positional and keyword arguments, returned values, exceptions and metadata.

Interview exercise

Wrap an async function.

Answer and reasoning

Use an async wrapper that awaits the underlying callable and preserves its error propagation and metadata.

Continue learning

Compare the scenario with the Python interview questions and test your understanding with the Python MCQs. For terminology and implementation details, consult the reference material.

More in Python

read ✓Python · hard

Python asyncio.gather and Timeouts

Run coroutines concurrently with asyncio.gather, enforce timeouts, and handle partial failures and cancellation correctly.

~2 min readread →
read ✓Python · mid

Python Bounded Async Worker Queues

Use asyncio.Queue and a fixed worker pool to bound pending work. Trace backpressure, shutdown and failure ownership.

~3 min readread →
read ✓Python · mid

Python Asyncio and Blocking Functions

Python Asyncio and Blocking Functions. Learn the reasoning, a practical example, common mistakes and an interview exercise.

~2 min readread →
esc