我有一个工作的memoize decorator,它使用Django的缓存后端在一定时间内记住函数的结果。我专门把它应用到一个类方法。在
我的装修师看起来像:
def memoize(prefix='mysite', timeout=300, keygenfunc=None):
# MUST SPECIFY A KEYGENFUNC(args, kwargs) WHICH MUST RETURN A STRING
def funcwrap(meth):
def keymaker(*args, **kwargs):
key = prefix + '___' + meth.func_name + '___' + keygenfunc(args, kwargs)
return key
def invalidate(*args, **kwargs):
key = keymaker(*args, **kwargs)
cache.set(key, None, 1)
def newfunc(*args, **kwargs):
# construct key
key = keymaker(*args, **kwargs)
# is in cache?
rv = cache.get(key)
if rv is None:
# cache miss
rv = meth(*args, **kwargs)
cache.set(key, rv, timeout)
return rv
newfunc.invalidate = invalidate
return newfunc
return funcwrap
我在一个类方法上使用这个方法,所以类似于:
^{pr2}$实际的记忆过程非常完美!也就是说,打电话给
myStorageUnitInstance.someBigCalculation()
正确使用缓存。好吧,酷!在
我的问题是,当我试图手动使一个特定实例的条目失效时,我想在这个实例中运行
myStorageUnitInstance.someBigCalculation.invalidate()
但是,这不起作用,因为“self”不能被传递,因此密钥也不能被生成。“索引超出我的索引范围”显示为“LamberDa”错误。在
当然,我可以成功地拨打:
myStorageUnitInstance.someBigCalculation.invalidate(myStorageUnitInstance)
这很好用。但当我已经在引用一个特定的实例时,它“感觉”是多余的。如何让Python将其视为实例绑定的方法,从而正确地填充“self”变量?在
虽然我同意AlexM的观点,但我确实有一些空闲时间,并认为这会很有趣:
注意,我已经将
^{pr2}$ 这个代码中有很多东西,所以它是否真的让你的生活更容易被考虑。在keygenfunc
签名从(*args,**kwargs)
改为(instance)
,因为这就是您在示例中使用它的方式(如果您从方法调用的参数而不是对象实例生成键,someBigCalculation.invalidate
方法不可能以您想要的方式清除缓存)。在必须始终在类上设置描述符,而不是在实例上设置描述符(有关所有详细信息,请参见the how-to guide)。当然,在本例中,您甚至不需要在实例上设置它,而是在另一个函数上设置它(并将其作为绑定方法的属性获取)。我认为使用语法的唯一方法是使funcwrap成为自定义类的实例(当然,该类必须是描述符类,即定义适当的
__get__
方法,就像函数本质上那样)。那么invalidate
可以是该类的一个方法(或者,也许更好的是另一个自定义类,其实例是前面提到的描述符类的__get__
方法生成的“绑定方法类实体”),并最终到达您所渴望的im_self
(这就是它在绑定方法中的命名方式)。在这是一个相当大的代价(概念和编码;-)为你所寻求的小便利付出的巨大代价,我真的不想花一两个小时来完全开发和测试它。但我希望我已经给了你足够明确的指示,让你继续做下去,如果你仍然热衷于这一点,我很乐意澄清和帮助你,如果有什么不清楚的东西或是什么东西阻碍了你的进展。在
相关问题 更多 >
编程相关推荐