不带括号的装饰器(不更改装饰器定义)

问题描述 投票:0回答:1

假设我有以下装饰器。 (要重复一个功能n次)

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

现在,它确实具有默认值4,但是,即使我想用默认值调用它,我仍然必须按以下方式调用它]

@repeat()
def my_function():
    print("hello")

代替

@repeat
def my_function():
    print("hello")

现在,我可以将装饰器的定义更改为

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)

并且如果需要,可以启用不带参数的功能来调用它。

但是,可以在不更改装饰器代码的情况下,而是通过定义另一个装饰器来实现这一点吗?

即我想要定义一个装饰器enable_direct,以便可以将@enable_direct添加到我的装饰器定义中,并具有相同的效果。 (即如下)

@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
python decorator python-decorators parentheses
1个回答
0
投票

最后,解决方案可能很简单:

import functools


def enable_direct(decorator):
    @functools.wraps(decorator)
    def wrapper(*args, **kwargs):
        return decorator(4)
    return wrapper


@enable_direct
def repeat_direct(num_times):
    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


def repeat(num_times):
    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


@repeat_direct(2)
def my_func(name):
    print(name)

@repeat(2)
def my_func2(name):
    print(name)

print(my_func)
print(my_func2)

my_func("Gino")
my_func2("Mario")

产生:

<function my_func at 0x7fc47d0acb70>
<function my_func2 at 0x7fc47d0acc80>
Gino
Gino
Gino
Gino
Mario
Mario
© www.soinside.com 2019 - 2024. All rights reserved.