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

Count function calls in python using decorator

我在 class 的一篇笔记中看到了下面的 python 片段。我理解高阶函数的概念和这里使用的记忆技术。但是我对 counted_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

为了计算函数被调用的次数,您可以这样做:

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 的装饰器,它添加了计数器所需的附加语句(计数器的初始化和增加)和 returns 装饰器功能。

def counted(n):
    counted.call_count += 1
    return f(n)

创建一个新函数,它有一个附加变量 counted.call_count,每次调用该函数时该变量都会增加。 return f(n) 然后调用该函数并且 return 是 return 值。

counted.call_count = 0
return counted

然后初始化计数器并 return 修饰函数。

现在是最后 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 版本除外)。这会让事情变得更容易...