Search code examples
pythondecoratorpython-decoratorsfunctools

Python - Count number of times function passes through decorator


I have a decorator that I wanna make increase a counter anytime a function is routed through the decorator. So far this is my code

from functools import wraps
def count_check(function):
    """Returns number of times any function with this decorator is called
    """
    count = []
    @wraps(function)
    def increase_count(*args, **kwargs):
        count.append(1)
        return function(*args, **kwargs), len(count)

    return increase_count

It works fine, until another function passes through the decorator and count resets to 0 for that function. How can I aggregate the total number of times?


Solution

  • This should do it:

    from functools import wraps
    def count_check(function, count=[0]):
        """Returns number of times any function with this decorator is called
        """
        @wraps(function)
        def increase_count(*args, **kwargs):
            count[0] += 1
            return function(*args, **kwargs), count[0]
    
        return increase_count
    

    You could also get fancy and use a dictionary counting the functions individually as well as separately:

    from functools import wraps
    def count_check(function, count={}):
        """Returns number of times any function with this decorator is called
        """
        count[function] = 0
        @wraps(function)
        def increase_count(*args, **kwargs):
            count[function] += 1
            return function(*args, **kwargs), count[function], sum(count.values())
    
        return increase_count
    

    Demo:

    @count_check
    def foo():
        return 42
    
    print(foo(), foo(), foo())
    
    @count_check
    def bar():
        return 23
    
    print(bar(), bar(), bar())
    print(foo(), foo(), foo())
    

    Prints:

    (42, 1, 1) (42, 2, 2) (42, 3, 3)
    (23, 1, 4) (23, 2, 5) (23, 3, 6)
    (42, 4, 7) (42, 5, 8) (42, 6, 9)