is there a way to track the number of times a function is called?

Solution 1:

This doesn't work for builtin functions, but an interesting approach would be:

def myfunction():
    myfunction.counter += 1
myfunction.counter = 0

You're giving the function an attribute, so every call that attribute is updated. No global variables needed.

Built-ins are read-only. They cannot be modified.

Solution 2:

You could use a decorator that tracks how many times the function is called. Since list is a built-in, you can't decorate or replace its pop method so you'd have to use your own list class, for example.

def counted(f):
    def wrapped(*args, **kwargs):
        wrapped.calls += 1
        return f(*args, **kwargs)
    wrapped.calls = 0
    return wrapped

class MyList(list):
    @counted
    def pop(self, *args, **kwargs):
        return list.pop(self, *args, **kwargs)

x = MyList([1, 2, 3, 4, 5])
for i in range(3):
    x.pop()

print x.pop.calls # prints 3

Solution 3:

i used the following little trick to track how many times the function was called

def myfun(s,i=[0]):    
    print(s)    
    i[0]+=1 # mutable variable get evaluated ONCE
    return i[0]

>>> myfun('aaa')
aaa
1
>>> myfun('bbb')
bbb
2

Solution 4:

Here is a simple and elegant solution for a self counting function, without any decorators, global variables, etc:

def hello():
    hello.counter += 1
    print(hello.counter)
hello.counter = 0

Each time you call hello(), it will print 1, 2, etc.

Let's not forget that, in Python, a function is a first-class citizen and it has rights. And one of them is to have attributes!

If you are willing to include your method call in a function, it can be easy:

def pop_counted(a):
    pop_counted.counter += 1
    return a.pop()
pop_counted.counter = 0

Voilà!

Comment

This works because a Python function "knows" itself (this is a necessary feature, so that functions can call themselves recursively if desired).

If you wish to keep some information about a function, it might be better to keep it where it belongs: in an attribute of the function.

The advantage of not using a global variable is scope:

  • no risk of name collisions in the global namespace
  • the information you were keeping will vanish as soon as the function is taken off the stack, which is what you want -- no garbage left.

A bonus is that this approach will work in cases where a global variable is not really a good option, typically for nested functions where you can't declare a "global" in the outer function.

Solution 5:

For kicks, I wrote up an answer using a decorator:

class counter:
    #wraps a function, to keep a running count of how many
    #times it's been called
    def __init__(self, func):
        self.func = func
        self.count = count

    def __call__(self, *args, **kwargs):
        self.count += 1
        return self.func(*args, **kwargs)

To use it, simply decorate a function. You can then check how many times that function has been run by examining the "count" attribute. Doing it this way is nice because:

1.) No global variables. The count is associated directly with the function.

2.) You can wrap builtin functions easily, by calling the class directly:

sum_wrapped = counter(sum)
sum_wrapped([1, 2 ,3, 4])
#outputs 10
print sum_wrapped.count
#outputs 1

Of course, this could be improved by using the Decorators module to keep the docstrings and other good things intact. Also, for an excellent overview of what decorators are, and how they work, check out this stackoverflow answer.