【发布时间】:2019-04-24 16:12:05
【问题描述】:
我一直在尝试使functools.lru_cache 实例具体化,如this answer 中所述,但是当用于__call__ 方法时,他们的解决方案失败了。
class test:
def __init__(self):
self.method = lru_cache()(self.method)
self.__call__ = lru_cache()(self.__call__)
def method(self, x):
print('method', end=' ')
return x
def __call__(self, x):
print('__call__', end=' ')
return x
b = test()
# b.method is cached as expected
print(b.method(1)) # method 1
print(b.method(1)) # 1
# __call__ is executed every time
print(b(1)) # __call__ 1
print(b(1)) # __call__ 1
所以__call__ 的结果在使用此方法包装时不会被缓存。 __call__ 上的缓存甚至不注册已调用的函数,并且不可散列的值不会引发错误。
print(b.method.cache_info())
# CacheInfo(hits=1, misses=1, maxsize=128, currsize=1)
print(b.__call__.cache_info())
# CacheInfo(hits=0, misses=0, maxsize=128, currsize=0)
print(b.call({})) # __call__ {}
print(b.method({})) # ... TypeError: unhashable type: 'dict'
【问题讨论】:
-
我试过你的代码,如果将
@lru_cache装饰器应用到__call__,它工作正常,但对于你的情况,你在初始化时将__call__分配给 self ,所以 lru 版本的__call__被添加到self.__dict__中,而实际上并未更改__call__方法。 -
@Enix 如果您的意思是通常装饰
__call__,那么是的,这适用于一个实例,但是一旦您有两个实例,就会共享缓存,并在一个实例上重置它会在其他实例,因此使用装饰器通常不起作用。 (我尽量不提出关于如何拥有特定于实例的缓存的问题,因为链接的问题涵盖了这一点)
标签: python caching magic-methods