If you don't want to rewrite your recursive function, you could also decorate it in a function that counts it using a counter of some sort. Example of an implementation:
UPDATE: I've changed the answer, but the old answer is kept at the end of the answer //UPDATE
Assume here that you have some recursion functions in some_module.py:
# From some_module.py def factorial(x): return factorial(x-1)*x if x > 1 else 1 def cumsum(x): return cumsum(x-1) + x if x > 1 else 1 def loopBST(root): # ... your code
And you want to apply the decorator to count how many recursions ran. Here, the code is performed inside some_function() to show that you don't have to keep the count variable(s) in the global scope. (See comments) (Also, the recursive functions are still in global space)
# Main file: from functools import wraps, partial from collections import defaultdict # import the two recursion functions from some_module.py from some_module import cumsum, factorial, loopBST def some_function(): global factorial, cumsum, loopBST def counting_recursion(fn, counter): @wraps(fn) def wrapper(*args, **kwargs): counter[fn.__name__] += 1 return fn(*args, **kwargs) return wrapper counters = defaultdict(int) my_deco = partial(counting_recursion, counter=counters) factorial = my_deco(factorial) cumsum = my_deco(cumsum) loopBST = my_deco(loopBST) print(factorial(3)) # 6 print(cumsum(5)) # 15 factorial_count = counters[factorial.__name__] cumsum_count = counters[cumsum.__name__] loopBST_count = counters[loopBST.__name__] # Equals 0: were not called in my example print('The "{}" function ran {} times'.format(factorial.__name__, factorial_count)) print('The "{}" function ran {} times'.format(cumsum.__name__, cumsum_count)) # The "factorial" function ran 3 times # The "cumsum" function ran 5 times
A few modifications/variations:
Instead of using my_deco = partial(counting_recursion, counter=counters), the recursive functions could be decorated directly:
cumsum = counting_recursion(cumsum, counter=counters) factorial = counting_recursion(factorial, counter=counters) loopBST = counting_recursion(loopBST, counter=counters)
Instead of using fn.__name__ to identify the called function, the counting_recursion-function could be rewritten as:
def counting_recursion(fn, counter): @wraps(fn) def wrapper(*args, **kwargs): counter[wrapper] += 1 return fn(*args, **kwargs) return wrapper
Then, to read the number from the counters dictionary:
factorial_count = counters[factorial] cumsum_count = counters[cumsum] loopBST_count = counters[loopBST]
If you want to read more about wrapping functions, check out https://stackoverflow.com/a/25827070/1144382 and the docs on wraps
OLD EXAMPLE:
from functools import wraps, partial class Counter: def __init__(self, start_count=0): self._counter = start_count def __repr__(self): return str(self._counter) def count(self): self._counter += 1 counter = Counter() def counting_recursion(fn, counter): @wraps(fn) def wrapper(*args, **kwargs): counter.count() return fn(*args, **kwargs) return wrapper my_deco = partial(counting_recursion, counter=counter) @my_deco def factorial(x): return factorial(x-1)*x if x > 1 else 1 print(factorial(3)) # 6 print('The {} function ran {} times'.format(factorial.__name__, counter)) # The factorial function ran 3 times
To implement this in your case, just make some counter and decorate your function:
@my_deco def loopBST(root): # ... print(counter._counter) # prints number of counts
Of course, you don't have to make a Counter-class to call counter.count() on, you could also have a dictionary of counters, e.g. counts[loopBST] += 1 or just an array with a single element count_list[0] += 1. (see the code example at top of this answer) (The entire point is to "hide" the value in a reference that is not rewritten when the variable is reassigned, which is why just an integer count count += 1 won't work.)