I would like to have a decorator that has two fields, let's say .ncalls
and .rdepth
. When it wraps a function, the ncalls should count how many times the function called itself and rdepth should represent maximum recursion depth achieved, if a function is recursive.
I've tried something like here (https://stackoverflow.com/a/51690214/12313533) but it doesn't work.
My code now looks like a hybrid of a previously mentioned and code to count function calls with a decorator:
def call_counter(func): #a decorator to count calls
def helper(x):
helper.calls += 1
return func(x)
helper.calls = 0
return helper
So i need something like this (this doesn't work):
def depthcounter(func):
def wrapper(*args, **kwargs):
wrapper.rdepth += 1
wrapper.ncalls += 1
result = func(*args, **kwargs)
return result
wrapper.ncalls = 0
wrapper.rdepth = 0
return wrapper
For example, let's say I have a factorial numbers producing function like
@depthcounter
def factorial(n):
if n <= 1:
return 1
else:
return n * factorial(n - 1)
#Here is some working code
print(factorial.ncalls, factorial.rdepth)
factorial(4)
print(factorial.ncalls, factorial.rdepth)
factorial(10)
print(factorial.ncalls, factorial.rdepth)
print(factorial.ncalls, factorial.rdepth)
factorial(20)
print(factorial.ncalls, factorial.rdepth)
factorial(2)
print(factorial.ncalls, factorial.rdepth)
And with the decorator I need it to produce this:
0 0
4 4
10 10
10 10
20 20
2 2
But I get this instead:
0 0
4 4
14 14
14 14
34 34
36 36
Decorators are executed as soon as the module is imported, so your assignment wrapper.ncalls = 0
is executed only once and not at every function call.
You need to keep track of starting number of counts inside of wrapper
function. here is a working piece of code:
def callcounter(func):
callcounter.ncalls = 0
def wrapper(*args, **kwargs):
initial_calls = callcounter.ncalls
callcounter.ncalls += 1
result = func(*args, **kwargs)
wrapper.ncalls = callcounter.ncalls - initial_calls
return result
return wrapper
@callcounter
def factorial(n):
if n <= 1:
return 1
else:
return n * factorial(n - 1)
factorial(4)
print(factorial.ncalls)
factorial(10)
print(factorial.ncalls)
Output
4
10