7

如何在不使用 Python 中的全局变量的情况下跟踪递归调用的数量。例如,如何修改以下函数来跟踪调用次数?

def f(n):
    if n == 1:
        return 1
    else:
        return n * f(n-1)

print f(5)
4

5 回答 5

10

这是一个不使用全局的巧妙技巧:您可以将计数器隐藏在函数本身中。

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

无论如何,这将处理“所有呼叫”的情况。

于 2013-01-25T01:14:24.407 回答
7

正如 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)(最长调用树的深度)或只是将两者相加(实际调用的总数)

于 2013-01-25T01:12:51.593 回答
6

此方法将为您提供函数运行的次数:

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)
于 2013-01-25T01:33:15.137 回答
4

这是一种使用堆栈而不是全局变量的方法。如图所示,它记录了对函数的调用次数,包括最初的调用次数,而不仅仅是函数对自身进行的递归调用次数。要做到这一点,只需将 移动到语句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)
于 2013-01-25T03:06:17.773 回答
0

您可以添加一个参数来保持调用计数(需要是可变的),它在函数开始时递增。

于 2013-01-25T01:11:13.137 回答