Search code examples
pythondecoratorpython-decorators

Does a decorator run once even if the decorated function was called many times?


so this code is supposed to count how many times a functions is called, but I'm trying to understand decorating in python more deeply and not just copying code, by running this code below

def counter(func):
    print('counter function executed')
    def wrapper(*args, **kwargs):
        print('wrapper function executed')
        wrapper.count += 1
        return func(*args, **kwargs)
    wrapper.count = 0
    return wrapper

@counter
def foo(i):
    return print(f'{i}')

foo('foo')
foo('foo')
foo('foo')
print(foo.count)

it outputs

counter function executed
wrapper function executed
foo
wrapper function executed
foo
wrapper function executed
foo
3

but decorating foo() should equal counter(foo)

why "counter function executed" was printed once ?? isn't it supposed to be printed every time foo() is called, does that mean decorating foo() actually equals to wrapper(foo) .... am I getting it right ???

I came to this conclusion because I thought that wrapper.counter would always equal 0 as counter(foo) would reset wrapper.counter value to 0.


Solution

  • The decorator runs only at the time the decorated function is defined, in order to modify the function definition. The function returned by the decorator (wrapper) is what gets executed each time the decorated function is called.