2017-07-24 84 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