Sometimes we want to provide more elaborate parameters to a decorator. The idea is that we are going to customize the wrapping function. When we do this, decoration becomes a two-step process.
When we write the following code, we provide a parameterized decorator to a function definition:
@decorator(arg) def func( ): pass
The use of the decorator is a shorthand for the following code:
def func( ): pass func= decorator(arg)(func)
Both examples do the following three things:
Defined a function,
func
Applied the abstract decorator to its arguments to create a concrete decorator,
decorator(arg)
Applied the concrete decorator to the defined function to create the decorated version of the function,
decorator(arg)(func)
This means that a decorator with arguments will require indirect construction of the final function. Let's tweak our debugging decorator yet again. We'd like to do the following:
@debug("log_name") def some_function( args ): pass
This kind of code...