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).
@foo(not just@foo()) and@foo(...).def repeatstatement 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.