Python decorators are just wrappers… that return functions
Part of my issue with understanding how decorators work was that I was treating them as a function/class that is returning a variable. I should have been thinking of them as a function/class returning a modified (i.e. decorated) function/class. As mentioned succinctly here, “Decorators are a form of metaprogramming; they enhance the action of the function or method they decorate.” So a decorator is just a wrapper of the function that you want to modify (that returns a function).
So if we want to decorate the function
func with the function
decor then the
sequence of evaluation would be
modified_func = decor(func)(func_args).
Before going into what a decorator is, it’s useful to understand what it isn’t.
Casually wrapping a function in another function may not be sufficient. To
Illustrate this I’ve created a function
to_decorate (a function that returns
its input divided by 2) that I want to decorate.
def to_decorate(x): return(x/2) to_decorate(2)
not_decorator function below does not act as a decorator even though it is
a wrapper for
not_decorator function is modifying the
to_decorate instead of modifying the
to_decorate function itself.
We have to actually evaluate the function that is the argument to
not_decorator. Because we have to evaluate it, the function that is the
not_decorator must also take in an argument. The result is that
this function ends up returning a variable rather than a function/class.
# modifying the output of func so func has to be evaluated not modified def not_decorator(func): return(abs(func))
The code below will error out since the
to_decorate function is looking for an
not_decorated = not_decorator(to_decorate)
Passing an argument will allow it to run, but it’s still not a decorator since it’s returning a variable instead of a function.
not_decorated = not_decorator(to_decorate(2)) print(not_decorated)
Let’s define the function
decorator which takes a function as an input,
evaluates the absolute value of the result of the function (the modification), a
returns a function as opposed to the result.
We have to wrap the modification in the
inner wrapper otherwise we won’t be
able to return a function/class. This was the issue with
What about modifying a function with multiple decorators?
What about passing arguments to decorators?