具有特定对象属性的全局缓存作为 python 中的输入

Global cache with specific object attributes as input in python

在尝试实现 class 级缓存装饰器时,我偶然发现了 ring 库,它能够全局保存函数的输入和输出。它基本上允许我实现以下行为,给定 Calculateclass 定义如下:

import ring

class Calculate:

    @ring.dict({})
    def sum(self, a, b):
       print('actually calculating')
       sum = a + b
       return sum

这是我试图通过 Calculate

实现的行为
>>> calculate = Calculate()
>>> calcualte.sum(5,7)
actually calculating
12

>>> different_calculate = Calculate()
>>> different_calculate.sum(5,7)
12    #this outputs 12 straight from the cache from first calculate. 
#Note that even if 'different_calculate' and 'calculate' are different instantiations of 'Calculate', the cache works at a class level. Therefore the sum is not actually REcalculated.

现在,我需要用 sum 实现相同的行为,这次是 属性。我在这里面临的问题是 @property def 作为参数 self。因此,当像前面的示例那样尝试缓存时,它将不起作用,因为输入不再是 num1num2,而是 self,它随每个实例化而变化。因此它永远不会在不同的 class 实例化时从缓存中提取,因为 self 总是随着每个实例化而改变。见下文:

import ring

class Calculate:
   def __init__(self, num1, num2):
      self.num1 = num1
      self.num2 = num2

    @ring.dict({})
    @property
    def sum(self):
       print('actually calculating')
       sum = num1 + num2
       return sum

>>> calculate = Calculate()
>>> calcualte.sum(5,7)
actually calculating
12

>>> different_calculate = Calculate()
>>> different_calculate.sum(5,7)
actually calculating
12

为了解决这个问题,我不得不告诉缓存库不要将 self 作为输入,而是 self.num1self.num2。然后代码将是这样的:

   @ring.dict(self.num1, self.num2)  # <--- this does not exist
    @property
    def sum(self):
       print('actually calculating')
       sum = num1 + num2
       return sum

有什么方法可以使用 ring 或任何其他 python 缓存库来实现吗?

因此,在从 here 中获得灵感后,我最终创建了自己的记忆功能,如下所示:

memo = {}

def memoize(*attrs):  
    def wrapper(f):  
        def helper(obj):
            key = tuple([getattr(obj,attr) for attr in attrs])
            if key not in memo:            
                memo[key] = f(obj)
            return memo[key]
        return helper
    return wrapper




class Calculate:
    def __init__(self, num1, num2):
        self.num1 = num1
        self.num2 = num2

    @property
    @memoize('num1', 'num2')  
    def sum(self):
        print('actually calculating')
        sum = self.num1 + self.num2
        return sum


>>> calculate = Calculate(6,9)
>>> calculate.sum
actually calculating
15

>>> another_calculate = Calculate(6,9)
>>> another_calculate.sum
15