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

时间:2018-10-29 22:19:30

标签: python-3.x function caching global memoization

在尝试实现类级别的缓存装饰器时,我偶然发现了ring库,该库能够全局存储函数的输入和输出。给定class的{​​{1}}定义,基本上可以实现以下行为:

Calculate

这是我尝试通过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作为参数。因此,当尝试像上一个示例中那样进行缓存时,它将不起作用,因为输入不再是selfnum1而是num2,它随每个实例化而改变。因此,它永远不会在不同的类实例上从缓存中拉出,因为self总是随每个实例而变化。见下文:

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 作为输入,而是将selfself.num1视为输入。然后代码将变成这样:

self.num2

我可以用 @ring.dict(self.num1, self.num2) # <--- this does not exist @property def sum(self): print('actually calculating') sum = num1 + num2 return sum 或其他任何python缓存库来实现此目的吗?

1 个答案:

答案 0 :(得分:0)

因此,从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