我在其中一个课堂笔记中看到了以下一段蟒蛇。我理解高阶函数的概念和这里使用的memoization技术。但是我对在最后几次分配之后count_fib和fib实际引用的内容感到困惑。谁能给我一些解释呢?
def count(f):
def counted(n):
counted.call_count += 1
return f(n)
counted.call_count = 0
return counted
def memo(f):
cache = {}
def memoized(n):
if n not in cache:
cache[n] = f(n)
return cache[n]
return memoized
def fib(n):
if n == 1 or n == 0:
return n
else:
return fib(n - 1) + fib(n - 2)
fib = count(fib)
counted_fib = fib
fib = memo(fib)
fib = count(fib)
print(fib(30))
print(fib.call_count)
print(counted_fib.call_count)
给出了结果:
832040
59
31
答案 0 :(得分:0)
为了计算调用函数的次数,你可以这样做:
def fib(n):
fib.count += 1 # increase counter
if n == 1 or n == 0:
return n
else:
return fib(n - 1) + fib(n - 2)
fib.count = 0 # initialize counter
print(fib(5)) # 5
print(fib.count) # 15
你的def count(f)
只是函数f
周围的装饰器,它添加了计数器所需的附加语句(计数器的初始化和增加)并返回修饰函数。
def counted(n):
counted.call_count += 1
return f(n)
创建一个新函数,它有一个额外的变量counted.call_count
,每次调用该函数时它都会增加。然后return f(n)
调用该函数并返回返回值。
counted.call_count = 0
return counted
然后初始化计数器并返回修饰函数。
现在最后3行:
fib = count(fib)
fib_counted = fib # save the counted function of the bare fib
fib_memo = memo(fib) # meomize fib
fib = count(fib_memo) # add a counter to the meomized version
print(fib(30))
print(fib.call_count) # 59: the meomized version was called
# ~2 times per distinct argument
print(fib_counted.call_count) # 31: i.e.: the memo called the original fib
# once per distinct argument.
是什么让所有有点难以阅读的事实是fib
函数调用自身(递归)。因此,函数不能被称为新名称(meomized版本除外)。这将使事情变得更容易......