首页 > 编程问答 >为什么 functools.cache 装饰器不能在我的带有记忆功能的斐波那契序列函数上工作?

为什么 functools.cache 装饰器不能在我的带有记忆功能的斐波那契序列函数上工作?

时间:2024-08-01 08:12:00浏览次数:10  
标签:python caching fibonacci memoization functools

我在 python 中搞乱了记忆,并使用了一个示例斐波那契序列函数作为模型。我将第一个 fibonacci() 函数编写为常规函数,无需记忆,它按预期工作。接下来,我编写了我的 fibonacci_memo() 函数,该函数使用带有输出的输入字典来利用记忆化,并且按预期工作。然后我想测试 functools 缓存装饰器,看看它是否达到了我预期的相同效果。因此,我复制了不使用记忆化的初始 fibonacci() 函数,并在其上添加了 @cache 装饰器。然而,结果是出乎意料的,因为它似乎与不使用记忆化的原始 fibonacci() 函数运行相同。

我是否对装饰器的实用性或一般记忆化有误解?代码如下,感谢任何帮助!

from functools import cache

def fibonacci(n):
    if n == 0:
        return 0
    elif n == 1:
        return 1
    return fibonacci(n - 1) + fibonacci(n - 2)

print(fibonacci(23))
# instant, works as expected

def fibonacci_memo(n, memo:dict={}):
    if n == 0:
        return 0
    elif n == 1:
        return 1
    if n in memo:
        return memo[n]
    memo[n] = fibonacci_memo(n - 1, memo) + fibonacci_memo(n - 2, memo)
    return fibonacci_memo(n - 1, memo) + fibonacci_memo(n - 2, memo)

print(fibonacci_memo(500))
# instant, works as expected

@cache
def fibonacci_functools(n):  # identical to first, basic fibonacci function
    if n == 0:
        return 0
    elif n == 1:
        return 1
    return fibonacci(n - 1) + fibonacci(n - 2)

print(fibonacci_functools(500))
# slow, shouldn't it be te same as fibonacci_memo()??

问题出在你的 fibonacci_functools 函数中,你调用的是 原始的 fibonacci 函数 ,而不是调用自身递归。这意味着它没有利用 @cache 装饰器提供的记忆化功能。

以下是如何修复它的方法:

from functools import cache

@cache
def fibonacci_functools(n):
    if n == 0:
        return 0
    elif n == 1:
        return 1
    return fibonacci_functools(n - 1) + fibonacci_functools(n - 2)  # 调用自身

print(fibonacci_functools(500))  # 现在应该很快了

通过在递归步骤中调用 fibonacci_functools ,装饰器可以缓存每个结果,从而产生与 fibonacci_memo 函数相同的性能提升。

标签:python,caching,fibonacci,memoization,functools
From: 78815634

相关文章

  • ffmpeg python 导致死锁
    我在使用ffmpegpython处理相机帧时遇到问题。我使用process.communicate()的第一种方法效果很好,但存在延迟问题。process=(ffmpeg.input('pipe:',format='rawvideo',pix_fmt='rgb24',s='{}x{}'.format(width,height))......
  • 将 HTTP 分块编码数据流代码片段从 Node.js 转换为 Python
    我有一个Node.js客户端代码,它将请求发送到HTTP服务器,然后连续接收分块编码数据。这是带有一些流量数据输出的Node.js代码。consthttp=require('http');constoptions={hostname:'...',path:'...',port:...,...};constreq=http.request(......
  • vsc python 调试器和 pylance 无法识别已安装的包
    我最近使用snowflake-connector-python在我的虚拟环境中安装了pipinstallsnowflake-connector-python[pandas]==2.7.6,当我在激活虚拟环境的情况下从命令行运行我的脚本时,它工作正常。我设置了与VSC解释器相同的虚拟环境,但尝试运行python调试器会引发异常......
  • 如何从python读取matlab持续时间对象
    我创建一个matlab持续时间对象并将其保存到.mat文件:timeend=seconds(123);save('time.mat',timeend,'-v7.3');然后我从python读取它:withh5py.File('time.mat','r')asf:var=f['timeend'][:]print(list(var))......
  • 通过 python 连接到 Snowflake 时出错“UnpicklingError: invalid load key, '\x00'
    我在使用snowflake.connector.connect通过python连接到snowflake时遇到以下错误importsnowflake.connector#pipinstallsnowflake-connector-python#iamgettingtheenvfrom.envfileistoredlocallycnx=snowflake.connector.connect(user=os.getenv('USER'),pass......
  • Python Selenium 单击 webdriverwait 与 find_element
    我无法理解这两个代码块之间的区别。发送点击在webdriverwait和find_elements中都有效。代码1fromseleniumimportwebdriverfromselenium.webdriver.common.byimportByfromselenium.webdriver.support.uiimportWebDriverWaitfromselenium.webdriver.suppo......
  • Python 问题 如何创建在 PDF 中注册为剪切线的专色?
    我正在开发一个项目,需要我在图像周围创建一条剪切线,但在任何RIP程序(例如Versaworks或Flexi)上将其注册为实际剪切线时遇到困难。我尝试了很多不同的方法python库可以帮助解决这个问题,但我无法让它工作。我希望它像我们在Illustrator中所做的那样,创建一条名为CutConto......
  • 使用Python时如何避免`setattr`(和`getattr`)?以及是否有必要避免
    如果我想向协议缓冲区中的字段添加一个在编译时未知的值,我目前正在做setattr我通常不喜欢使用setattr,因为它看起来不太安全。但是当我知道该对象是protobuf时,我认为这很好,因为我设置它的值必须是protobuf允许的类型。所以也许它并不是真的不安全?让我举......
  • Java sshtools 生成的 EDDSA 签名与 Python 的 pycryptome 生成的签名不匹配
    我有一个python库,它使用pycryptodomelibrary使用openssh格式的ED25519私钥使用Ed25519算法对数据进行签名。然后需要使用sshtools库和相应的公钥在Java应用程序中验证签名。但是签名验证失败。约束:从文件中读取私钥/公钥很重要。我无法......
  • Elastic python请求超时错误:池达到最大大小,不允许更多连接
    我正在使用Elasticsearchpython模块。我正在尝试像这样建立到服务器的连接es=Elasticsearch([config.endpoint],api_key=config.key,request_timeout=config.request_timeout)服务器连接,然后我尝试执行丰富策略。es.enr......