简体   繁体   English

python装饰器* args和** kwargs

[英]python decorators *args and ** kwargs

I'm brand new to coding and I've been trying to absorb as much as possible. 我是编码的新手,我一直在努力吸收尽可能多的东西。 I don't understand a lot of the technical explanations you guys post, so please try to keep it in simple English. 我不了解你们发布的很多技术说明,因此请尽量使用简单的英语。 I get the mechanics of how a decorator function works, but my issue is following the code logic - specifically why we have to add *args and ** kwargs. 我了解装饰器功能的工作原理,但是我的问题是遵循代码逻辑-特别是为什么我们必须添加* args和** kwargs。 Is it correct to state that whatever we pass in to the decorator function that takes in a function which has arguments, will always pass the same arguments into the wrapper function because it's nested within the decorator? 声明我们传入装饰器函数的任何传入具有参数的函数是否总是将相同的参数传递给包装函数是正确的,因为它嵌套在装饰器中? That's what I'm missing here. 那就是我在这里想念的。 I don't understand how the arguments from the original function get passed in. 我不明白原始函数的参数是如何传递的。

Let's take a simple example: 让我们举一个简单的例子:

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

You're right that the reason we need to take *args, **kwargs is so that we can pass that same *args, **kwargs on to the wrapped function. 没错,我们需要使用*args, **kwargs是为了使我们可以将相同的*args, **kwargs传递给包装函数。

This is called "forwarding", or "perfect forwarding". 这称为“转发”或“完美转发”。 The idea is that tracing doesn't have to know anything about the function it's wrapping—it could take any set of positional and keyword arguments, and return anything, and the wrapper still works. 这个想法是, tracing不必知道有关其包装的函数的任何信息,它可以接受任何位置和关键字参数集,并返回任何内容,并且包装器仍然有效。


For some decorators, that isn't appropriate. 对于某些装饰器,这是不合适的。 For example, a decorator that's designed to cache a set of functions that all have the same API, using one specific parameter as the cache key, could use *args, **kwargs and then munge through the list and dict to find that specific parameter, but it's a lot simpler, and cleaner, to be explicit: 例如,一个装饰器旨在使用一个特定的参数作为缓存键来缓存所有具有相同API的一组函数, 可以使用*args, **kwargs ,然后仔细检查列表和字典以查找该特定参数,但是要明确得多:

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

But there are a lot more generic decorators than specific ones. 但是,通用装饰器要比特定装饰器多得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM