一日一技:實現函數調用結果的 LRU 緩存

一日一技:實現函數調用結果的 LRU 緩存

一日一技:實現函數調用結果的 LRU 緩存

攝影:產品經理
在工程項目中,可能有一些函數調用耗時很長,可是又須要反覆屢次調用,而且每次調用時,相同的參數獲得的結果都是相同的。在這種狀況下,咱們可能會使用變量或者列表來存放,例如:算法

resp_1 = get_resp(param=1)
resp_2 = get_resp(param=2)
resp_3 = get_resp(param=3)

可是,若是返回的結果佔用內存比較大,咱們每次調用都把結果存在內存裏面,就會消耗大量內存。緩存

因而,咱們可使用 LRU 算法:最近最常使用的參數生成的結果,咱們存下來,下次遇到相同的參數時直接返回結果。而不常出現的參數,等到須要的時候再計算。計算完成後,也先存下來。可是若是緩存空間不夠了,不常使用的會先刪除。ide

LRU 的算法本身手動實現起來比較麻煩,但好在 Python 的 functions模塊已經提供了現成的 lru_cache裝飾器供咱們使用。函數

首先咱們寫一個不帶 lru 算法的程序:code

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}')

運行效果以下圖所示:
一日一技:實現函數調用結果的 LRU 緩存blog

從運行結果能夠看到,調用函數三次,第一次和第三次傳入的參數都是 kingname,第二次傳入的參數爲 產品經理, 你好:kingname打印了兩次, 你會:產品經理打印了一次。第二次打印的時間比第一次多了10秒,第三次打印的時間比第二次多了10秒。內存

如今咱們把 LRU 緩存加上。get

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}')
tie.sleep(10)
now = say('產品經理')
print(f'如今時間爲:{now}')
time.sleep(10)
now = say('kingname')
print(f'如今時間爲:{now}')

一日一技:實現函數調用結果的 LRU 緩存

從打印出來的結果能夠看出,第三次調用 say函數的時候,傳入的也是 kingname,可是函數根本沒有運行,因此沒有打印第二個 你好:kingname。而且第三個時間與第一個時間徹底相同。說明第三次調用函數的時候,直接讀取的緩存。產品

lru_cache(maxsize=128,typed=False)接收兩個參數,第一個參數 maxsize表示最多緩存多少個結果,這個數字建議設置爲2的冪。超出這個結果就會啓用 LRU 算法刪除不經常使用的數據。第二個參數 typed表示是否檢查參數類型,默認爲 False,若是設置爲 True,那麼參數 3和 3.0會被當作不一樣的數據處理。hash

因爲 lru_cache底層是基於字典來實現的緩存,因此參數都必須是 hashable 的,不然會致使報錯。

相關文章
相關標籤/搜索