python decorators * args和** kwargs

时间:2018-03-20 04:28:46

标签: python decorator

我对编码很陌生,而且我一直试图尽可能地吸收。我不太了解你们发布的很多技术解释,所以请尽量用简单的英语。我得到了装饰器函数如何工作的机制,但我的问题是遵循代码逻辑 - 特别是为什么我们必须添加* args和** kwargs。声明无论我们传入装饰器函数接受带有参数的函数,它都会正确地将相同的参数传递给包装函数,因为它嵌套在装饰器中吗?这就是我在这里失踪的地方。我不明白原始函数的参数是如何传入的。

1 个答案:

答案 0 :(得分:2)

我们举一个简单的例子:

def tracing(func):
    @functools.wraps
    def wrapper(*args, **kwargs):
        logging.debug(f'Calling {func.__name__}')
        try:
            return func(*args, **kwargs)
        finally:
            logging.debug(f'Called {func.__name__}')
    return wrapper

@tracing
def spam():
    print('spam')

@tracing
def add3(n):
    return n+3

您是对的,我们需要采用*args, **kwargs的原因是我们可以将相同的*args, **kwargs传递给包装函数。

这称为"转发"或"完美转发"。我们的想法是tracing不必知道它包装的功能 - 它可以采用任何一组位置和关键字参数,并返回任何内容,并且包装器仍然可以工作。 / p>

对于一些装饰者来说,这是不合适的。例如,设计用于缓存一组所有具有相同API的函数的装饰器,使用一个特定参数作为缓存键,可以使用*args, **kwargs然后munge通过列表和字典找到特定的参数,但它更简单,更清晰,更明确:

def caching_spam(func):
    cache = {}
    @functool.wraps
    def wrapper(eggs, beans, spam, cheese):
        if spam not in cache:
            cache[spam] = func(eggs, beans, spam, cheese)
        return cache[spam]
    return wrapper

但是除了特定的装饰器之外,还有更多的通用装饰器。