實現函數調用結果的 LRU 緩存


在工程項目中,可能有一些函數調用耗時很長,但是又需要反復多次調用,並且每次調用時,相同的參數得到的結果都是相同的。在這種情況下,我們可能會使用變量或者列表來存放,例如:

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,那么參數 33.0會被當做不同的數據處理。

由於 lru_cache底層是基於字典來實現的緩存,所以參數都必須是 hashable 的,否則會導致報錯。

 

分享自:公眾號:未聞code


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM