在工程項目中,可能有一些函數調用耗時很長,但是又需要反復多次調用,並且每次調用時,相同的參數得到的結果都是相同的。在這種情況下,我們可能會使用變量或者列表來存放,例如:
resp_1 = get_resp(param=1) resp_2 = get_resp(param=2) resp_3 = get_resp(param=3)
但是,如果返回的結果占用內存比較大,我們每次調用都把結果存在內存里面,就會消耗大量內存。
於是,我們可以使用 LRU 算法:最近最常使用的參數生成的結果,我們存下來,下次遇到相同的參數時直接返回結果。而不常出現的參數,等到需要的時候再計算。計算完成后,也先存下來。但是如果緩存空間不夠了,不常使用的會先刪除。
LRU 的算法自己手動實現起來比較麻煩,但好在 Python 的 functions
模塊已經提供了現成的 lru_cache
裝飾器供我們使用。
首先我們寫一個不帶 lru 算法的程序:
import time import datetime def say(name): print(f'你好:{name}') now = datetime.datetime.now() return now now = say('kingname') print(f'現在時間為:{now}') time.sleep(10) now = say('產品經理') print(f'現在時間為:{now}') time.sleep(10) now = say('kingname') print(f'現在時間為:{now}')
運行效果如下圖所示:
從運行結果可以看到,調用函數三次,第一次和第三次傳入的參數都是 kingname
,第二次傳入的參數為 產品經理
, 你好:kingname
打印了兩次, 你會:產品經理
打印了一次。第二次打印的時間比第一次多了10秒,第三次打印的時間比第二次多了10秒。
現在我們把 LRU 緩存加上。
import time import datetime from functools import lru_cache @lru_cache(maxsize=32) def say(name): print(f'你好:{name}') now = datetime.datetime.now() return now now = say('kingname') print(f'現在時間為:{now}') time.sleep(10) now = say('產品經理') print(f'現在時間為:{now}') time.sleep(10) now = say('kingname') print(f'現在時間為:{now}')
從打印出來的結果可以看出,第三次調用 say
函數的時候,傳入的也是 kingname
,但是函數根本沒有運行,所以沒有打印第二個 你好:kingname
。並且第三個時間與第一個時間完全相同。說明第三次調用函數的時候,直接讀取的緩存。
lru_cache(maxsize=128,typed=False)
接收兩個參數,第一個參數 maxsize
表示最多緩存多少個結果,這個數字建議設置為2的冪。超出這個結果就會啟用 LRU 算法刪除不常用的數據。第二個參數 typed
表示是否檢查參數類型,默認為 False
,如果設置為 True
,那么參數 3
和 3.0
會被當做不同的數據處理。
由於 lru_cache
底層是基於字典來實現的緩存,所以參數都必須是 hashable 的,否則會導致報錯。
分享自:公眾號:未聞code