1

the task is to call a function 4 times using decorator. The solution is:

def my_decorator (func):
    def wrapper():
        func()
        func()
        func()
        func()
    return wrapper

@my_decorator
def printer_hp():
    print('I am printer HP 4700 LaserJet')
    return 0

printer_hp()

HOWEVER, if I move func to the wrapper args and put parentheses for the @my_decorator:

def my_decorator ():
    def wrapper(func):
        func()
        func()
        func()
        func()
    return wrapper

@my_decorator()
def printer_hp():
    print('I am printer HP 4700 LaserJet')
    return 0

the function is called automatically 4 times without calling it in the main program. Why is that?

DDR
  • 459
  • 5
  • 15
  • There is a great (though lengthy) explanation, that really helps understanding decorators: https://stackoverflow.com/questions/739654/how-to-make-a-chain-of-function-decorators/1594484#1594484 – Sebastian Loehner Sep 28 '18 at 11:18

1 Answers1

3

Because when you do:

@my_decorator()
def printer_hp():
    ...

It is equivalent to:

printer_hp = my_decorator()(printer_hp)

Since my_decorator() returns wrapper, it is then equivalent to:

printer_hp = wrapper(printer_hp)

And what wrapper does is call the given function 4 times, which is why printer_hp is called 4 times right away.

blhsing
  • 91,368
  • 6
  • 71
  • 106
  • Was typing up something similar. Might want to include that with `()` basically follows the same behavior as decorators with arguments. Here's a good thread on it: https://stackoverflow.com/questions/5929107/decorators-with-parameters You'd basically want a third outer function to accept the decorator's args; in this case, none. – wholevinski Sep 28 '18 at 11:18