[英]python resettable memoization decorator (for a certain instance)
这个问题是对python resettable instance method memoization decorator的回答的后续。 事实上,我会写这个作为对该答案的评论,但我没有(但我希望)足够的声誉。
在那个答案中,@aix 提供了一种使用装饰器重置记忆化函数的好方法。
该答案的“问题”在于,为某个装饰方法调用reset
重置所有实例的缓存。 使用@aix 定义的相同类的示例应该清楚地说明:
c = my_class()
print c.my_func(55)
# This time the function is computed and stored in cache
print c.my_func(55)
# This second call is cached... no computation needed
d = my_class()
d.my_func.reset()
print c.my_func(55)
# This third call is also computed, since the cache has been cleared
我认为d.my_func.reset()
只清除缓存的预先计算值d.my_func
,而不是对所有其他实例my_class
。
我有一个不能完全说服的半解决方案,但我想有人可以改进。
我修改了reset()
方法并引入了一个参数instance
:
def _reset(self,instance):
for cached in self.cache.keys():
if cached[0] == instance:
del self.cache[cached]
现在,如果我这样做:
c = my_class()
print c.my_func(55)
# This time the function is computed and stored in cache
print c.my_func(55)
# This second call is cached
d = my_class()
d.my_func.reset(d)
print c.my_func(55)
# Now this third call is cached
但是,调用 reset 方法的方式: d.my_func.reset(d)
看起来(至少)丑陋,但我一直没能找到更好的解决方案......有没有人有一些想法?
谢谢!
编辑
作为记录:您可以通过修改装饰器的__get__
方法获得相同的行为,而不是将实例作为参数传递。
添加self.original_self = obj
在__get__(self, obj, objtype)
方法和替代if cached[0] == instance
与if cached[0] == self.original_self
在_reset
方法。 这解决了问题!
2 种可能性 - 也存储在实例__dict__
而不是全局备忘录 dict 中:
def MemoMeth(meth):
"""Memoizer for class methods (uses instance __dict__)
Example:
class C:
@MemoMeth
def slowmeth(self, a, b): ...
"""
class _MemoMeth:
def __init__(self, this):
self.this = this
def __call__(self, *args):
memo = self.this.__dict__.setdefault(_MemoMeth, {})
try:
return memo[args][1]
except:
memo[args] = tr = time.time(), meth(self.this, *args)
return tr[1]
def reset(self):
self.this.__dict__.setdefault(_MemoMeth, {}).clear()
return property(_MemoMeth)
这个为每次访问使用线程本地存储而不是新的包装器对象:
def MemoMeth3(meth):
"""Memoizer for class methods (uses instance __dict__)
Example:
class C:
@MemoMeth3
def slowmeth(self, a, b): ...
"""
tls = threading.local()
class MemoProperty(object):
def __call__(self, *args):
memo = tls.instance.__dict__.setdefault(self, {})
try:
return memo[args][1]
except:
memo[args] = tr = time.time(), meth(tls.instance, *args)
return tr[1]
def reset(self):
tls.instance.__dict__.setdefault(self, {}).clear()
def __get__(self, instance, owner):
tls.instance = instance
return self
return MemoProperty()
您可以使用该方法的__self__
属性(在本例中为self.__self__
)来查找它绑定到的类实例(而不必同时传递该实例)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.