使用装饰器在python中计算函数调用

时间:2017-01-20 18:48:01

标签: python fibonacci memoization python-decorators

我在其中一个课堂笔记中看到了以下一段蟒蛇。我理解高阶函数的概念和这里使用的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

1 个答案:

答案 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版本除外)。这将使事情变得更容易......