Function/method decorator is something misunderstood by many developers: beginner but also more confirmed one.
Python like other language like Java have this concept of function decoration
that can be used to modify behavior or inject content. You probably already
see some, it is the line before a function declaration starting with an
The most common one in python is probably
@property. A built-in decorator
that transform a method into a property (i.e. call an unbound method).
To understand how decorator works you must understand how python will apply it. If you have something like:
divide(2, 3) you will in fact call
Let’s pretend that the goal of this decorator is to format the returned number into a string representing a float with a 2 digits precision. The implementation will be as follows:
This is basically how to write a decorator in python. The first argument of the decorator is the decorated function/method. The decorator returns a wrapper that will accept some parameters (here the same as the function) and will be responsible to do whatever he want when called (here format the results).
The problem with this implementation is that if you try to get the name or even
the docstring of the function will be get the wrapper one. To solves this
problem you have to use the
decorator inside your decorator. It will correctly set all the decorated
function attribute for you. Previous decorator will now looks like:
Maybe we now want to define per decorated method the format precision. Here is how parameters can be used with decorator:
There is a little hack here in order to generate the string format and then
format the result, but it is not the important thing here. In order to add a
parameter to the decorator we have to wrap another time the function: the first
level is just here to get the precision, it is in fact the second level
decorated) which is the decorator like previously. This make takes some time
get it clear but once understood you have all the logic.
Now to set the prevision to 3 we will write:
You now master python decorator, you should be able to easily rewrite the
@property of the standard lib in python instead of C.
To conclude decorator can be very useful and can be used in a wide range of applications. One of my favorite are:
@cached_propertyfrom werkzeug that allows you to cache the return value of a property, very useful when fetching resource is resource consuming and value is static for the current object.
@login_requiredfrom django that check that a user is authenticated.
@routefrom flask that register a new route in your app.