Suppose I have the following decorator. (To repeat a function n times)
def repeat(num_times=4):
def decorator_repeat(func):
@functools.wraps(func)
def wrapper_repeat(*args, **kwargs):
for _ in range(num_times):
value = func(*args, **kwargs)
return value
return wrapper_repeat
return decorator_repeat
Now, it does have a default value of 4, however, even if I want to call it with default value, I still have to call it as follows
@repeat()
def my_function():
print("hello")
instead of
@repeat
def my_function():
print("hello")
Now, I can change the definition of my decorator to
def repeat(_func=None, *, num_times=2):
def decorator_repeat(func):
@functools.wraps(func)
def wrapper_repeat(*args, **kwargs):
for _ in range(num_times):
value = func(*args, **kwargs)
return value
return wrapper_repeat
if _func is None:
return decorator_repeat
else:
return decorator_repeat(_func)
And enable the functionality to call it without arguments if I want to.
However, can this be achieved without changing the code of the decorator, but by defining another decorator?
i.e. I want to define a decorator enable_direct
so that I can just add @enable_direct
to my decorator definition and have the same effect. (i.e. as follows)
@enable_direct
def repeat(num_times=4):
def decorator_repeat(func):
@functools.wraps(func)
def wrapper_repeat(*args, **kwargs):
for _ in range(num_times):
value = func(*args, **kwargs)
return value
return wrapper_repeat
return decorator_repeat
Note:
I am aware of the solution mentioned in How to create a Python decorator that can be used either with or without parameters?
The definitions in that question have a different signature, and if one is starting afresh, one can follow that pattern. However, say I have 20-30 such decorator definitions (3 level nested). I want all of these to be enabled to be called without parentheses.
The def repeat
statement does not have a function argument. The functions in that question have a 2 level nesting, while mine has 3 level. I wanted to ask if it is possible with such decorator definitions (which are meant to be called with parentheses) without changing the function definition. The accepted answer there has a different signature, and thus does not meat requirement in this question.
Note 2: I did not ask this question before trying out the definition of double wrap given there. Calling it without parentheses returns another function (if the signature of function is as described).