一些函数参数可以通过装饰器传递吗?

Posted

技术标签:

【中文标题】一些函数参数可以通过装饰器传递吗?【英文标题】:Can some function arguments be passed through decorators? 【发布时间】:2016-06-06 13:19:15 【问题描述】:

我有一个功能 -

def add(a, b):
   return a+b

现在我希望它使用装饰器将 100 添加到结果中 -

@decorator(100)
def add(a, b):
    return (a+b)

class decorator():
    def __init__(self, c):
        self.c = c

    def __call__(self, f):
        def _wrapped_f(a, b):
            return self.c + f(a, b)
        return _wrapped_f

问题是当我想保留额外的参数变量而不是固定为 100。

有点像 -

@decorator(c)
    def add(a, b):
        return (a+b)

我可以在函数调用期间以某种方式分配这个变量的值吗? (当调用 add 函数时) 我想使用装饰器执行此操作的原因是因为我不想修改我的函数添加。

我无法在函数中提供额外的参数,例如 -

def(a, b, c=0):
    return (a+b+c)

因此,需要装饰者。

【问题讨论】:

也就是说,你想让装饰器给函数添加额外的参数? 是的,完全正确。如果不是通过装饰器,还有其他方法可以在不修改实际功能的情况下做到这一点。 好吧,您可以更改 _wrapped_f 以采用 (*args, **kwargs)` 参数,然后将所有这些参数相加,但我真的不明白您将如何定义如何在一般情况下处理这些附加参数。当然,仅仅添加更多的东西来添加到结果中并不总是有意义的。 “我无法在函数中提供额外的参数...” 我认为您需要详细说明这一点。为什么不能使用额外的参数?了解这一限制似乎是找到不同解决方案的关键。 【参考方案1】:

当然。装饰器所做的只是用包装的版本替换原始函数;该包装器可以采用任意数量的参数。

我不确定您为什么要使用类 - 作为标准装饰器会更清楚。

def decorator(func):
    def wrapped(a, b, c):
        return c + func(a, b)
    return wrapped

@decorator
def add(a, b):
    return (a+b)

【讨论】:

谢谢。全新的装饰器。没想到这么简单。【参考方案2】:

不是 100% 确定你想用这个装饰器做什么,所以这可能不是你想要的,但即便如此,其他人可能会觉得它很有用。

可以向函数添加另一个参数,只需向_wrapped 函数添加更多参数,或者甚至将*args**kwargs 传递给该函数。但是你如何处理这些参数呢?当然,仅将这些参数添加到结果中仅对 add 函数有意义。

在一般情况下,您可以使用修饰函数本身来处理附加参数。然后,只需使用原函数的修饰函数reduce所有参数即可:

from functools import reduce # Python 3
def vararg(f):
    """ change two-arg-function into vararg-function"""
    def _f(*args):
        return reduce(f, args)
    return _f

@vararg
def add(a, b):
    return a + b

print(add(1, 2))           # ->  3
print(add(1, 2, 3))        # ->  6
print(add(1, 2, 3, 4))     # -> 10
print(add(1, 2, 3, 4, 5))  # -> 15

【讨论】:

以上是关于一些函数参数可以通过装饰器传递吗?的主要内容,如果未能解决你的问题,请参考以下文章

Python-4 函数和装饰器

如何将装饰器中的变量传递给装饰函数中的函数参数?

Python 装饰器强制显式传递参数

你能写一个可以接受任意数量参数的 c# 装饰器函数吗?

将命令行参数传递给调用带有装饰器参数的装饰函数的函数

Python中带参数的装饰器