如何在不使用 Python 中的全局变量的情况下跟踪递归调用的数量。例如,如何修改以下函数来跟踪调用次数?
def f(n):
if n == 1:
return 1
else:
return n * f(n-1)
print f(5)
这是一个不使用全局的巧妙技巧:您可以将计数器隐藏在函数本身中。
def f(n):
f.count += 1
if n == 1:
return 1
else:
return n * f(n-1)
之后:
>>> f.count = 0 # initialize the counter
>>> f(5)
120
>>> f.count
5
>>> f(30)
265252859812191058636308480000000L
>>> f.count
35
无论如何,这将处理“所有呼叫”的情况。
正如 delnan 所说,如果你想要所有调用,那么没有全局是不可能的,所以我假设你只想要调用depth,你只需要添加一个返回值
def f(n):
if n == 1:
return 1,0
else:
x, call_depth= f(n-1)
return n * x, call_depth+1
如果您正在处理几个递归调用,您可以做一个max(call_depth1, call_depth2)
(最长调用树的深度)或只是将两者相加(实际调用的总数)
此方法将为您提供函数运行的总次数:
def f(n):
if hasattr(f,"count"):
f.count += 1
else:
f.count = 1
if n == 1:
return 1
else:
return n * f(n-1)
这是一种使用堆栈而不是全局变量的方法。如图所示,它记录了对函数的调用次数,包括最初的调用次数,而不仅仅是函数对自身进行的递归调用次数。要做到这一点,只需将 移动到语句ncalls += 1
的开头。else
def f(n, ncalls=0):
ncalls += 1
if n == 1:
return 1, ncalls
else:
res, ncalls = f(n-1, ncalls)
return n * res, ncalls
for n in xrange(1, 6):
print 'f({}): {:4d} ({} calls)'.format(n, *f(n))
输出:
f(1): 1 (1 calls)
f(2): 2 (2 calls)
f(3): 6 (3 calls)
f(4): 24 (4 calls)
f(5): 120 (5 calls)
您可以添加一个参数来保持调用计数(需要是可变的),它在函数开始时递增。