如果你有一个递归函数(例如Fibonacci序列):
def fib(n):
"""Return Fibonacci of n; assumes n is an int >= 0."""
if n == 0 or n == 1:
return 1
else:
return fib(n-1) + fib(n-2)
如何计算,例如,当调用fib(20)时,fib(2)发生的次数?
答案 0 :(得分:2)
你可以使用装饰者:
import functools
def count(f):
"""Count function calls."""
@functools.wraps(f)
def counted(*args, **kwargs):
counted.count_calls += 1
return f(*args, **kwargs)
counted.count_calls = 0
return counted
fib = count(fib)
fib(5)
fib.count_calls
# 15
或者,您现在可以使用此装饰器和@
符号添加任何函数定义:
@count
def fib(n):
...
fib(5)
fib.count_calls
# 15
注意,这个装饰器会累积函数调用:
fib(5)
fib(5)
fib.count_calls
# 30
这是一个利用鲜为人知的function attributes的聪明实现。请注意,原始装饰器是根据他在lecture on Memoization中讨论的John DiNero的count
函数进行修改的,在那里他解决了这个特定问题。
答案 1 :(得分:1)
您可以使用字典来计算fib
的所有调用。在第一次调用fib
之前必须清除字典。
calls = defaultdict(int)
在函数中,在执行任何其他操作之前更新字典中的相应条目:
def fib(n):
global calls
"""Assumes n an int >= 0
Returns Fibonacci of n"""
calls[n] += 1
if n == 0 or n == 1:
return 1
else:
return fib(n-1) + fib(n-2)
答案 2 :(得分:1)
怎么样:
def fib(n, counts_dict):
counts_dict[n] += 1
if n == 0 or n == 1:
return 1
else:
return fib(n-1, counts_dict) + fib(n-2, counts_dict
counts_dict = collections.defaultdict(int)
答案 3 :(得分:1)
这就是我的尝试...认为工作正常
def fib(n):
global counter
if (n == 0 or n == 1):
counter=counter+1
return 1
else:
counter=counter+1
return fib(n-1) + fib(n-2)
def countfib(n):
global counter
counter = 0
fib(5);
global count
count=counter
counter = 0
return count
counter=0
count=0
print fib(5)
count=countfib(5)
print count
输出:
8
15
答案 4 :(得分:1)
我不清楚你想要计算的重复值是什么,所以我猜它是用同一个参数调用(递归)函数的次数(或者它们的组,如果超过一个)。
在下面的代码中,名为tally_recurring_args()
的装饰器用于将函数包装在某些代码中以执行此操作。为了简化操作并避免重新发明轮子,collections.Counter
用于计算函数的每个唯一参数组合的调用次数。这是函数的一个属性,因此可以在wrapper
每次调用装饰函数时轻松引用它。
import collections
import functools
def tally_recurring_args(func):
func._args_counter = collections.Counter() @ add attribute to func
@functools.wraps(func)
def wrapper(*args):
key = ', '.join(str(arg) for arg in args)
func._args_counter[key] += 1
return func(*args)
return wrapper
@tally_recurring_args
def fib(n):
"""Return Fibonacci of n; assumes n is an int >= 0."""
if n == 0 or n == 1:
return 1
else:
return fib(n-1) + fib(n-2)
print('fib(5) -> {}'.format(fib(5)))
for args, count in sorted(fib._args_counter.items()):
print('fib({}): called {} time{}'.format(args, count,
's' if count > 1 else ''))
输出:
fib(5) -> 8
fib(0): called 3 times
fib(1): called 5 times
fib(2): called 3 times
fib(3): called 2 times
fib(4): called 1 time
fib(5): called 1 time
答案 5 :(得分:0)
def fib(n, x):
c = 1 if n == x else 0
if n == 0 or n == 1:
return 1, c
else:
fA, cA = fib(n - 1, x)
fB, cB = fib(n - 2, x)
return fA + fB, cA + cB + c
如果我没有弄乱逻辑,则此函数接受n
和x
并返回元组(y, c)
s.t.在计算过程中fib(n, _)=y
和fib(x, _)
被调用了c
次。
这是涉及更新字典的其他提议解决方案的更纯粹的替代方案。它基于这样的假设,即OP仅需要为一个特定f(k, _)
调用k
的次数,因此避免填写只需要一个值的字典。
答案 6 :(得分:0)
没有全局变量:
from collections import defaultdict
def fib(n, count=None):
if count is None:
count = defaultdict(int)
count[n] += 1
if n in (0, 1):
return 1, count
return fib(n - 1)[0] + fib(n - 2)[0], count
fib
函数现在返回一个元组:第一个元素是所需的值,第二个元素是一个字典,其中包含调用fib
函数的每个值的次数的信息。 / p>
答案 7 :(得分:0)
如何使用函数属性。就像一个静态变量。
def fib(n):
"""Return Fibonacci of n; assumes n is an int >= 0."""
If hasattr(fib, 'cnt'):
fib.cnt += 1
else:
fib.cnt = 1
if n == 0 or n == 1:
return 1
else:
return fib(n-1) + fib(n-2)
fib.cnt =0
答案 8 :(得分:0)
使用全局:
c = 0
def fib(n):
global c
c += 1
if n == 1:
return 0
elif n == 2:
return 1
else:
return fib(n-1) + fib(n-2)
答案 9 :(得分:0)
这是另一个没有全局变量的解决方案,但是通过传递值来完成:
def fibo(n, c):
if n <= 2 and n > 0:
return n-1, c
else:
n1, c1 = fibo(n-1,c+1)
n2, c2 = fibo(n-2,1)
return n1+n2, c1+c2