Meta decorator with parameters, defined in explicit functions
dieter
dieter at handshake.de
Tue Jun 28 03:26:30 EDT 2016
Ben Finney <ben+python at benfinney.id.au> writes:
> I want an explicit replacement for a common decorator idiom.
>
> There is a clever one-line decorator that has been copy-pasted without
> explanation in many code bases for many years::
>
> decorator_with_args = lambda decorator: lambda *args, **kwargs: lambda func: decorator(func, *args, **kwargs)
>
> My problem with this is precisely that it is clever: it explains nothing
> about what it does, has many moving parts that are not named, it is
> non-obvious and lacks expressiveness.
I have been able to understand the purpose of the definition above -
based solely on background knowledge about "decorator" and the definition.
A decorator is a function which takes a function as argument and
returns another function, the decorated function.
In its simplest form, it is usually is used like:
@decorator
def f....
However, there is a more complex use: a decorator with arguments.
It takes the form
@decorator(...args...)
def f...
In this use, the decorator is not "decorator" itself but
"decorator(...args...)". "decorator" itself is in fact a "meta" decorator
taking arguments and returning the real decorator.
The standard way to define such a meta decorator would be to have
a local function definition in its body and return that.
Locally defining functions and returning them looks a bit nasty in
Python. You might want to avoid it. That's what the
"decorator_with_args" above tries to facilitate.
It allows you to define a function "decorator"
with arguments "func, *args, **kw", decorate it with
"decorator_with_args" and use this as a decorator with arguments
("*args, **kw).
"decorator_with_args" essentially is a signature transform.
It transforms a function "func, *args, **kw --> ..." into
a function "*args, **kw --> func --> ..." *AND*
it does this in a completely natural and understandable way.
More information about the Python-list
mailing list