python 如何对方法进行记忆化

3 投票
3 回答
3649 浏览
提问于 2025-04-16 23:41

假设我有一个方法,可以根据给定的参数创建一个字典:

def newDict(a,b,c,d): # in reality this method is a bit more complex, I've just shortened for the sake of simplicity
    return { "x": a,
             "y": b,
             "z": c,
             "t": d }

还有另一个方法,每次执行时都会调用这个新字典的方法。因此,当我最后查看我的性能分析工具时,我看到的结果大概是这样的:

17874 calls (17868 primitive) 0.076 CPU seconds

当然,我的这个新字典方法被调用了 1785 次。现在,我的问题是,是否可以把这个新字典的方法进行缓存,这样就能减少调用次数?(为了确保,变量几乎在每次调用时都会改变,不过我不确定这是否会影响缓存这个函数的效果)

附加问题:我觉得 17k 次调用太多了,代码效率不高。但是通过查看这些统计数据,你能告诉我这是正常的结果,还是说我调用次数太多,导致代码运行缓慢吗?

3 个回答

2

记忆化的目的是为了保存那些执行起来比较耗费资源的操作的结果,这样在后续需要用到这个结果时,就不用再重复执行这个耗费资源的操作了。

记忆化通常应用于这样的函数:第一,它执行的操作比较耗费资源;第二,给定相同的输入参数时,它总是返回相同的结果;第三,它对程序的状态没有副作用。

在这样的函数中,记忆化的实现方式是“保存”结果和产生这个结果的输入参数的值。这其实是一种缓存的特殊形式。每次调用这个函数时,函数会先检查它的缓存,看当前输入参数的结果是否已经计算过。如果缓存中有这个结果,就可以直接返回,而不需要重新计算。

你的函数似乎每次被调用时都打算创建一个新的字典。看起来没有合理的方法来进行记忆化,因为你总是希望返回一个新的字典,以免它的使用会干扰到其他对这个函数的调用。

我能想到的唯一记忆化的方式是,如果(1)计算结果中的一个或多个值的过程比较耗费资源(在这种情况下,我可能会定义一个计算值的函数并对其进行记忆化),或者(2)newDict函数打算在给定特定参数值的情况下返回相同的一组值。在后者的情况下,我不会使用字典,而是会使用一个不可修改的对象(例如,一个像字典一样的类,但有保护措施防止修改其内容)。

关于你的子问题,你需要问自己两个问题:(1)newDict被调用的次数是否合适;(2)能否减少每次执行newDict的时间。这是两个独立的问题,需要分别处理。

顺便提一下,你的函数定义中有个小错误——return和左大括号之间不应该有个'd'。

8

如果你说的“记忆”是指“备忘录”,那么可以使用 functools.lru_cache。这是一种函数装饰器。

9
  1. 你是说 memoize,而不是 memorize
  2. 如果这些值几乎总是不同的,使用缓存(memoizing)反而会让事情变慢,没什么帮助。
  3. 如果不看到你完整的代码,也不知道它应该做什么,我们怎么能判断17,000次调用算多还是少呢?

撰写回答