Python › Async Generators & Async Context Managers

How would you implement an async context manager that also supports being used as a decorator, similar to contextlib.contextmanager's decorator support?

Advanced

Answer

contextlib.AsyncContextDecorator (or simply using @asynccontextmanager, which already supports this) lets the same async context manager be applied either with 'async with' OR as a decorator on an async function, automatically wrapping the entire function call in the context manager's enter/exit logic.
from contextlib import asynccontextmanager

@asynccontextmanager
async def timed():
    start = time.monotonic()
    try:
        yield
    finally:
        print(f"Took {time.monotonic() - start:.2f}s")

@timed()
async def slow_operation():
    await asyncio.sleep(1)
Real-world example Building a reusable async timing or logging decorator that can ALSO be used explicitly as an 'async with' block when needed.

Common follow-ups: What's the underlying mechanism that lets a single @asynccontextmanager-decorated function support both usages?