【发布时间】:2010-12-15 17:26:36
【问题描述】:
我有一个可用的 memoize 装饰器,它使用 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
我在类方法上使用它,所以类似于:
class StorageUnit(models.Model):
@memoize(timeout=60*180, keygenfunc=lambda x,y: str(x[0].id))
def someBigCalculation(self):
...
return result
实际的记忆过程完美无缺!也就是调用
myStorageUnitInstance.someBigCalculation()
正确使用缓存。好的,酷!
我的问题是当我尝试手动使特定实例的条目无效时,我希望能够在其中运行
myStorageUnitInstance.someBigCalculation.invalidate()
但是,这不起作用,因为“self”没有被传入,因此密钥没有被生成。如前所示,我收到指向我的 lambda 函数的“IndexError: tuple index out of range”错误。
当然可以成功调用:
myStorageUnitInstance.someBigCalculation.invalidate(myStorageUnitInstance)
这很完美。但是当我已经在引用一个特定的实例时,它“感觉”是多余的。如何让 Python 将其视为实例绑定方法,从而正确填写“self”变量?
【问题讨论】:
标签: python class scope methods decorator