Decorators for Coroutines

Difficulties with decorating coroutines

Since pretty much everything in Python is an object, pretty much anything can be decorated, and this includes coroutines as well. Coroutines are functions that can be suspended and resumed during execution, and are essential for enabling concurrency in programs.

However, there's a caveat here, and that is that asynchronous programming in Python introduces some differences in syntax. Therefore, these syntax differences will also be carried to the decorator.

Simply speaking, if we were to write a decorator for a coroutine, we could simply adapt to the new syntax. (Remember to await the wrapped coroutine and define the wrapped object as a coroutine itself, meaning the internal function will likely have to use async def instead of just def).

The problem lies in whether we want to have a decorator widely applicable to functions and coroutines. In most cases, creating two decorators would be the simplest (and perhaps best) approach, but if we wanted to expose a simpler interface for our users (by having fewer objects to remember), we could create a thin wrapper, acting like a dispatcher to two internal (not exposed) decorators. This would be like creating a facade but with a decorator.

A decorator that works for both functions and coroutines

There is no general rule about how hard it is to create a decorator for functions and coroutines, because that depends on the logic we want to put in the decorator itself. For example, in the code below there is a decorator that changes the parameters of the functions it receives, and this will work both for a regular function or a coroutine:

Get hands-on with 1400+ tech skills courses.