Decorators are syntactic sugar for wrapping functions inside other functions, like this:
How to build and use them
To pass in parameters and return values to and from a decorated function, we need to do this:
Using *args
and **kwargs
makes the decorator much more dynamic because it can be then used with functions that take any number of arguments, instead of hard coding the arguments in.
To pass parameters into the decorator itself, we need a decorator creator function:
To maintain/expose the name, docstrings and so on of decorated functions, one should use functools.wraps
:
Use cases
To intercept calls
Decorators can be used to run checks on the function call and decide if the original code is being run or a separate function is run.
For example, functools.cache
checks if there is a cached value. Django’s django.contrib.auth.decorators.login_required
checks if the user is authenticated and offers a redirectable login view instead if not. pydantic.validate_call
checks if function input matches the types and if not, raises an error.
To register functions
Some decorators return the original function back instead of wrapping it. Instead, they keep track of the references to that function.
Flask uses this approach to register endpoints with functions:
Other resources
Luciano Ramalho - Decorators and descriptors decoded - PyCon 2017 - YouTube
and
Katie Silverio Decorators, unwrapped How do they work PyCon 2017 - YouTube
Katie words it really well when she says (paraphrased): “Decorators make it clear that it’s something extra that is not inherit to the original function”
Katie walks through decorator functionality step by step:
- Writing it directly to source → mixes up utility code with the main logic
- Creating a wrapper function that is passed the function and function arguments that will be run → is annoying to add around every function call
- A partial that returns a new function that does both timer wrapping and the original logic
- Assign that partial to the same name as the original definition = decorating a function!
A 3-part series of tutorials for decorators