首页 > 解决方案 > 如何将参数作为装饰器发送给类?

问题描述

我有以下演示脚本,其中有两个装饰器(嵌套)。一个是validNumber函数返回包装器,用于测试传递给装饰函数的参数是否为正,另一个addExtra是一个类,将前一个装饰器的输出加上一个。

def validNumber(f):
    def wrapper(*args):
        for arg in list(args):
            if arg < 0:
                raise AttributeError('The number can\'t be negative')
        return f(*args)
    return wrapper

class addExtra:
    def __init__(self, fun):
        self.fun = fun
    def __call__(self, *args):
        total = self.fun(*args)
        if total < 100:
            total += 1 # I want to make it dynamic.
        return total

@addExtra
@validNumber
def sumOfNumbers(*args):
    return sum(list(args))

现在如您所见,我手动将“1”添加到参数总数中。但我想让它动态化。喜欢:

@addExtra(4) # add 4 to the total
@addExtra(2) # add 2 to the total

更新 由于社区提出了另一个具有类似问题的问题。我执行以下操作

class addExtra:
    def __init__(self, extra):
        self.extra = extra

    def __call__(self, fun):
        @functools.wraps(fun)
        def decorated(*args, **kwargs):
            total = fun(*args)
            if total < 100:
                total += self.extra  # I want to make it dynamic.
            return total
        return decorated 

并得到

TypeError: call () 接受 2 个位置参数,但给出了 4 个

有人可以在这里解释一下,而不是重定向到其他问题或答案吗?甚至我也想知道这里@functools.wraps 的使用。

标签: pythondecoratorpython-decorators

解决方案


为了能够将参数传递给您的装饰器,您必须创建一个返回装饰器的函数。

def addExtra(number):
    def decorator(*args, **kwargs):
        def wrapper(fun):
            total = fun(*args, **kwargs)
            if total < 100:
                total += number
            return total
        return wrapper

推荐阅读