In Python I know a little about decorators. In my poor understanding a decorated funtion declaration returns whatever the decorator function constructs with the original function (most reasonably this should be a callable):
def deco(func):
def func_wrapper(name):
return func(name)+", how are you?"
return func_wrapper
@deco
def foo(name):
return "Hello "+name
print(foo("Michael"))
This gives:
Hello Michael, how are you?
But what if a decorator is specified along with an argument:
def deco2(info):
def info_decorator(func):
def func_wrapper(name):
return func(name) + info
return func_wrapper
return info_decorator
@deco2(", how are you?")
def foo2(name):
return "Hello "+name
print(foo2("Regina"))
giving
Hello Regina, how are you?
What is the "rule" for handling this decorator?
It seems, that instead of returning foo2
Python first calls deco2
with the given arg, and assumes, that this call first constructs a factory for a decorator, which then acts like before with foo2 passed to it in order to return the final wrapper. However, in this case there is one additional "layer" involved (three defs instead of two), which makes it hard for me, to identify the general rule.
If you apply the decorator without arguments, e.g. @foo
, then the decorator takes the function being decorated as its argument and is expected to return any callable that will replace the decorated function.
If you apply the decorator with arguments, e.g. @foo('bar')
, then the decorator is expected to return a callable that will take the decorated function as its argument and return and callable that will replace the decorated function.
Put another way: a decorator without arguments only needs the function being decorated, but a decorator with arguments needs its own arguments and it needs to get a hold of the function being decorated somehow. Since the arguments to the decorator are arbitrary and not restricted in any way, it's hard to come up with any non-restrictive rules on how to additionally pass the decoratee to it as well. In that case the two-step process is applied: get decorator arguments, then return another callable that takes the decoratee.