nalzok
nalzok

Reputation: 16127

What does this decorator of decorator do?

I'm reading this answer to understand what decorators are and what can they do, from which my question emerges. The author provide a bonus snippet, which can make any decorator accept generically any argument, and this snippet really confused me:

def decorator_with_args(decorator_to_enhance):
    def decorator_maker(*args, **kwargs):
        def decorator_wrapper(func):
            return decorator_to_enhance(func, *args, **kwargs)
        return decorator_wrapper
    return decorator_maker

@decorator_with_args 
def decorated_decorator(func, *args, **kwargs): 
    def wrapper(function_arg1, function_arg2):
        print "Decorated with", args, kwargs
        return func(function_arg1, function_arg2)
    return wrapper

@decorated_decorator(42, 404, 1024)
def decorated_function(function_arg1, function_arg2):
    print "Hello", function_arg1, function_arg2

decorated_function("Universe and", "everything")

This outputs:

Decorated with (42, 404, 1024) {}
Hello Universe and everything

My question is: What exactly does decorator_with_args do?

Seems that it takes a decorator as its argument, wrap it with a decorator maker that accept arbitrary arguments, which are passed to the argument decorator, and return that decorator maker. This means decorator_with_args actually turns a decorator into a decorator maker. Sounds impossible, right? Anyway, I think it's tricky to tell its function.

And yes, the original code contains many comments, but I failed to get the answer from them, so I removed them to make the code shorter and cleaner.


Upvotes: 0

Views: 116

Answers (1)

nalzok
nalzok

Reputation: 16127

In short, decorator_with_args turns a function call like this:

function(func, *args, **kwargs)

to this form:

function(*args, **kwargs)(fund)

Note that both function call return another function.

Upvotes: 1

Related Questions