緩存裝飾器
緩存裝飾器與參數(shù)檢查十分相似,不過它重點是關(guān)注那些內(nèi)部狀態(tài)不會影響輸出的函數(shù)。每組參數(shù)都可以鏈接到唯一的結(jié)果。這種編程風(fēng)格是函數(shù)式編程的特點,當(dāng)輸入值有限時可以使用。
因此,緩存裝飾器可以將輸出與計算它所需要的參數(shù)放在一起,并在后續(xù)的調(diào)用中直接返回它。這種行為被稱為memoizing。
例子
我們下面創(chuàng)建一個使用裝飾器緩存技術(shù),實現(xiàn)記錄在一定時間內(nèi)函數(shù)是否被調(diào)用的例子,來解釋裝飾器用于緩存的用法。
準(zhǔn)備工作
首先我們準(zhǔn)備引入相關(guān)的包,time用于獲取當(dāng)前時間,hashlib用于轉(zhuǎn)換成哈希值,pickle用于將多個參數(shù)打包成一個對象,cache變量代表的是對函數(shù)返回值和時間的緩存。
import time
import hashlib
import pickle
cache = {}
依賴函數(shù)
def is_obsolete(entry, duration):
return time.time() - entry['time'] > duration
def compute_key(function, args, kw):
key = pickle.dumps((function.__name__, args, kw))
return hashlib.sha1(key).hexdigest()
is_obsolete函數(shù)是用來比較上次函數(shù)訪問時間(entry[‘time’],entry是一個字典,entry[‘time’]存儲的就是上次訪問的時間)與當(dāng)前時間(time.time())的間隔是否大于指定間隔(duration)的函數(shù)。
compute_key函數(shù)將傳入的function,args,kw打包并轉(zhuǎn)換成二進(jìn)制形式,作為函數(shù)與參數(shù)對應(yīng)的唯一標(biāo)識。
構(gòu)建修飾器
def memoize(duration=10):
def _memoize(function):
def __memoize(*args, **kw):
key = compute_key(function, args, kw)
# 是否已經(jīng)擁有它了?
if (key in cache and
not is_obsolete(cache[key], duration)):
print('we got a winner')
return cache[key]['value']
# 計算
result = function(*args, **kw)
# 保存結(jié)果
cache[key] = {
'value': result,
'time': time.time()
}
return result
return __memoize
return _memoize
在__memoize函數(shù)中,先使用compute_key函數(shù)獲取十六進(jìn)制的哈希值,作為唯一關(guān)鍵詞。然后查詢是否存在于緩存中(cache)并且時間是否滿足條件,如果均滿足則直接返回上次的運(yùn)行結(jié)果。否則重新計算結(jié)果并將結(jié)果存入緩存(cache)后返回。
測試
我們首先創(chuàng)建一個實現(xiàn)加法運(yùn)算的函數(shù)
@memoize()
def add(a, b):
# 如果在執(zhí)行這個計算時計算機(jī)過熱
# 請考慮中止程序
return a + b
如果我們用以下代碼測試
print(add(1, 2))
print(add(1, 2))
print(add(2, 2))
得到的運(yùn)行結(jié)果如下:
3
we got a winner
3
4
第二次調(diào)用add(1, 2)時因為前面已經(jīng)調(diào)用過了,所以就直接給出提示返回結(jié)果,而add(2, 2)是一個新的參數(shù)的運(yùn)算,所以進(jìn)行了再次重復(fù)的運(yùn)算。
下面我們來看一下如果超時會有怎樣的結(jié)果,由于默認(rèn)的menoize參數(shù)是10,所以我們這里改成1文章來源:http://www.zghlxwxcb.cn/news/detail-822693.html
@memoize(1) # 1秒后令緩存失效
def add(a, b):
return a + b
print(add(2, 3))
time.sleep(2)
print(add(2, 3))
我們使用time.sleep沉睡兩秒
運(yùn)行結(jié)果是文章來源地址http://www.zghlxwxcb.cn/news/detail-822693.html
5
5
到了這里,關(guān)于Python高級用法:裝飾器用于緩存的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!