具有特定对象属性的全局缓存作为 python 中的输入
Global cache with specific object attributes as input in python
在尝试实现 class 级缓存装饰器时,我偶然发现了 ring
库,它能够全局保存函数的输入和输出。它基本上允许我实现以下行为,给定 Calculate
的 class
定义如下:
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
。因此,当像前面的示例那样尝试缓存时,它将不起作用,因为输入不再是 num1
和 num2
,而是 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.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
有什么方法可以使用 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
在尝试实现 class 级缓存装饰器时,我偶然发现了 ring
库,它能够全局保存函数的输入和输出。它基本上允许我实现以下行为,给定 Calculate
的 class
定义如下:
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
。因此,当像前面的示例那样尝试缓存时,它将不起作用,因为输入不再是 num1
和 num2
,而是 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.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
有什么方法可以使用 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