Python内置装饰器:@lru_cache 和 @cache【leetcode808. 分汤】

Python内置装饰器:@lru_cache@cache

@lru_cache@cache 是Python标准库中提供的两种缓存装饰器,它们可以将函数计算的结果缓存起来,下次调用的时候直接返回结果

@lru_cache

@lru_cache 装饰器位于 functools 模块中,它使用最近最少使用(LRU)算法来缓存函数调用的结果。当你使用这个装饰器时,函数的调用结果将根据参数被缓存起来。如果再次出现相同的参数,函数将直接从缓存中获取结果,而不是重新执行,从而提高效率。

from functools import lru_cache

@lru_cache(maxsize=128)
def expensive_function(param):
    # 进行一些计算密集型的操作
    return result

在上面的例子中,expensive_function 是一个计算密集型的函数,我们使用 @lru_cache 来缓存它的结果。maxsize 参数指定了缓存中可以存储的最大调用次数。如果没有设置 maxsize 或者设置为 None,则缓存不会自动清除,但可能会消耗大量内存。

@cache

@cache 装饰器是Python 3.10中引入的新特性,它提供了一个简单的缓存机制。与 @lru_cache 不同,@cache 不需要任何外部库,它是内建于Python中的。@cache 装饰器的工作原理类似于 @lru_cache,但它更简洁,且默认情况下不限制缓存大小。

def expensive_function(param):
    # 进行一些计算密集型的操作
    return result

expensive_function = cache(expensive_function)

或者使用装饰器的语法:

@cache
def expensive_function(param):
    # 进行一些计算密集型的操作
    return result

注意

@lru_cache(maxsize=None) 与@cache 看起来是一样的,但是因为@cache内部不涉及缓存容量管理和调度等操作,理论上是要比@lru_cache(maxsize=None)更快的,在不需要管理缓存容量的时候,选择 @cache 可能更优

示例

leetcode808. 分汤
有 A 和 B 两种类型 的汤。一开始每种类型的汤有 n 毫升。有四种分配操作:

  • 提供 100ml 的 汤A 和 0ml 的 汤B 。
  • 提供 75ml 的 汤A 和 25ml 的 汤B 。
  • 提供 50ml 的 汤A 和 50ml 的 汤B 。
  • 提供 25ml 的 汤A 和 75ml 的 汤B 。

当我们把汤分配给某人之后,汤就没有了。每个回合,我们将从四种概率同为 0.25 的操作中进行分配选择。如果汤的剩余量不足以完成某次操作,我们将尽可能分配。当两种类型的汤都分配完时,停止操作。

注意 不存在先分配 100 ml 汤B 的操作。

需要返回的值: 汤A 先分配完的概率 + 汤A和汤B 同时分配完的概率 / 2。返回值在正确答案 10e-5 的范围内将被认为是正确的。

思路

直接模拟整个分汤的过程即可,类似于遍历一棵四叉树。叶子结点的概率根据题面写即可,分支结点的概率就是其子结点概率之和乘以0.25(条件概率的知识)
我们会发现这样做可能会出现可以从多条路径都能到达同一个结点的情况,比如 【操作2,操作4】 【操作3,操作3】和【操作4,操作2】会到达同一个节点。这就会导致不必要的重复计算。

这里我们就需要用到记忆化搜索。也就是将计算的结果保存下来,下一次直接使用。
手动实现就不说了,这里我们直接使用@cache即可

代码

class Solution:
    def soupServings(self, n: int) -> float:
        if n>4476:
            return 1
        actions=[(100,0),(75,25),(50,50),(25,75)]
        @cache
        def fun(a,b):         
            ret=0
            for action_a,action_b in actions:              
                if a<=action_a and b>action_b:
                    ret+=0.25
                elif a<=action_a and b<=action_b:
                    ret+=0.125
                elif a>action_a and b>action_b:
                    ret += fun(a-action_a,b-action_b)*0.25
            return ret
        return fun(n,n)

2024/4/2
  • 36
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值