How to count function calls using decorators?

The important thing to remember about decorators is that a decorator is a function that takes a function as an argument, and returns yet another function. The returned value – yet another function – is what will be called when the name of the original function is invoked.

This model can be very simple:

def my_decorator(fn):
    print("Decorator was called")
    return fn

In this case, the returned function is the same as the passed-in function. But that’s usually not what you do. Usually, you return either a completely different function, or you return a function that somehow chains or wraps the original function.

In your example, which is a very common model, you have an inner function that is returned:

def helper(x):
    helper.calls += 1
    return func(x)

This inner function calls the original function (return func(x)) but it also increments the calls counter.

This inner function is being inserted as a “replacement” for whatever function is being decorated. So when your module foo.succ() function is looked up, the result is a reference to the inner helper function returned by the decorator. That function increments the call counter and then calls the originally-defined succ function.

Leave a Comment