2017-07-24 51 views
1

我有一个方法/属性multiplier的对象。这个方法在我的程序中被调用了很多次,所以我决定使用它来提高执行速度。正如预期的那样,它的速度要快得多:在更新类的属性时清除某些方法的lru_cache?

下面的代码显示问题:

from functools import lru_cache 

class MyClass(object): 
    def __init__(self): 
     self.current_contract = 201706 
     self.futures = {201706: {'multiplier': 1000}, 
         201712: {'multiplier': 25}} 

    @property 
    @lru_cache() 
    def multiplier(self): 
     return self.futures[self.current_contract]['multiplier'] 

CF = MyClass() 
assert CF.multiplier == 1000 

CF.current_contract = 201712 
assert CF.multiplier == 25 

第二届assert失败,因为缓存值1000作为lru_cache()是不知道基础属性current_contract改变。

有更新self.current_contract时清除缓存的方法吗?

谢谢!

回答

2

是很简单:让current_contract读/写性能和清除缓存在属性的setter:

from functools import lru_cache 

class MyClass(object): 
    def __init__(self): 
     self.futures = {201706: {'multiplier': 1000}, 
         201712: {'multiplier': 25}} 
     self.current_contract = 201706 

    @property 
    def current_contract(self): 
     return self._current_contract 

    @current_contract.setter 
    def current_contract(self, value): 
     self._current_contract = value 
     type(self).multiplier.fget.cache_clear() 

    @property 
    @lru_cache() 
    def multiplier(self): 
     return self.futures[self.current_contract]['multiplier'] 

注:我假设你的实际使用情况涉及昂贵的计算,而不是一个单纯的字典查找 - 其他lru_cache可能有点矫枉过正;)

+0

其实它只是一个字典查找,但它在程序中被称为数十万次,并且使用lru_cache取得了很大的改变。我将用新代码再次测试它。 非常感谢您的帮助!它解决了这个问题。 – agiap

+2

如果您有这样的优化需求,您可能希望在'multiplier'中使用'self._current_contract'而不是'self.current_contract'(以避免属性调用/方法调用/属性解析开销),并且可能只是使乘法器一个在'current_contract' setter中设置的普通属性(请注意,我没有进行任何基准测试,因此您可能首先需要'timeit'来找出哪个解决方案确实是最快的) –

+0

这就是我所做的,将尽快进行测试。感谢您的建议。 – agiap