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