0

I have the following demo script where I have two decorators (nested). One is validNumber which is a function return wrapper to test the arguments passed to the decorated function are positive or not and Another one is addExtra which is a class to plus the output of the previous decorator with one.

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))

Now as you can see I manually add '1' to the total of the arguments. But I want to make it dynamic. Like:

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

UPDATE As community suggests another question with a similar problem. I do the following

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 

and getting

TypeError: call() takes 2 positional arguments but 4 were given

Can someone please explain here instead of redirect to some other question or answer? Even I also want to know the use of @functools.wraps here.

Sachin Kumar
  • 3,001
  • 1
  • 22
  • 47

1 Answers1

-1

To be able to pass arguments to your decorator you have to create a function that returns a decorator.

def addExtra(number):
    def decorator(*args, **kwargs):
        def wrapper(fun):
            total = fun(*args, **kwargs)
            if total < 100:
                total += number
            return total
        return wrapper
Omar Aflak
  • 2,918
  • 21
  • 39
  • The question is about accepting arguments in the decorator as a class. – VisioN May 14 '21 at 15:27
  • In the way it is written it doesn't change a thing. Moreover what I have posted still holds if you return a class from the method. – Omar Aflak May 14 '21 at 15:29