我用functools.lru_cache来实现斐波纳契数组,用的是备忘录.但我不了解我的输出生成的点击数.我的代码如下:

@lru_cache(maxsize=8)
def fib(n):
    if n <2:
        return n
    else:
        return fib(n-1) + fib(n-2)
print(fib(30))
print(fib.cache_info())

输出为 CacheInfo(hits=28, misses=31, maxsize=8, currsize=8)个 我知道未命中的次数是31(fib(0),...fib(30)) 但点击量应该是58次.例如,fib(2)应该对fib(0)和fib(1)命中,而对fib(2)命中.因此,每个呼叫都会产生一次未命中和两次命中.

我试着在网上搜索,但没有得到多少相关的结果.

推荐答案

但点击量应该是58次.

不要忘记,当命中时,递归停止.

当计算fib(n-1) + fib(n-2)时,fib(n-2)调用将立即命中,因为fib(n-1)已经确保它被缓存,因此fib(n-2)调用中不会出现进一步的递归(也不是命中).唯一的例外是当第二个项是f(0)时:第一个项没有计算f(0),因为1被认为是基本情况,所以在这里正确的项仍然表示未命中且没有命中.

但一般原则(忽略例外)在递归的每个级别上都是正确的:这个和的第二项只会命中一次,其他什么都不会.那里没有递归.唯一的递归发生在第一项的求值时.

f(5)年的可视化:

                       miss __f(5)__
                           /        \
                 miss __f(4)__     f(3) hit
                     /        \
           miss __f(3)__     f(2) hit
               /        \
     miss __f(2)__     f(1) hit
         /        \ 
 miss f(1)       f(0) miss (the exception)
        |          |
       base       base
 

因此,对于f(5),我们有6(=n+1)个未命中和3(=n-2)个命中.将这个推理应用于f(30),你就得到了报告的结果.

注意:缓存需要至少保留three个最近访问的结果.因此,即使您使用@lru_cache(maxsize=3),您也会得到相同的命中和未命中计数.当 Select 小于3的值时,缓存将变得无用.

Python相关问答推荐

如何在图片中找到这个化学测试条?OpenCV精明边缘检测不会绘制边界框

三个给定的坐标可以是矩形的点吗

将两只Pandas rame乘以指数

Excel图表-使用openpyxl更改水平轴与Y轴相交的位置(Python)

Python解析整数格式说明符的规则?

如何在Raspberry Pi上检测USB并使用Python访问它?

PyQt5,如何使每个对象的 colored颜色 不同?'

在Django admin中自动完成相关字段筛选

在Python中使用if else或使用regex将二进制数据如111转换为001""

Python—为什么我的代码返回一个TypeError

如果包含特定值,则筛选Groupby

30个非DATETIME天内的累计金额

如何反转一个框架中列的值?

为什么Visual Studio Code说我的代码在使用Pandas concat函数后无法访问?

替换包含Python DataFrame中的值的<;

在一个数据帧中,我如何才能发现每个行号是否出现在一列列表中?

递归链表反转与打印语句挂起

在不中断格式的情况下在文件的特定部分插入XML标签

关于数字S种子序列内部工作原理的困惑

在Django REST框架中定义的URL获得404分