Python開發:緩存機制介紹
譯文【51CTO快譯】在今天的文章中,我們將一同從簡單示例出發,了解如何使用緩存機制。在此之后,我們將進一步利用Python標準庫的functools模塊創建適合自己需要的緩存。閑言少敘,馬上開始。
緩存是一種將定量數據加以保存以備迎合后續請求的處理方式,旨在加快數據的檢索速度。在今天的文章中,我們將一同從簡單示例出發,了解如何使用緩存機制。在此之后,我們將進一步利用Python標準庫的functools模塊創建適合自己需要的緩存。作為起步工作,我們首先創建一個類,用于構建我們的緩存字典,而后根據需要進行擴展。以下為具體代碼:
- ########################################################################
- class MyCache:
- """"""
- #----------------------------------------------------------------------
- def __init__(self):
- """Constructor"""
- self.cache = {}
- self.max_cache_size = 10
在以上類示例中沒有包含什么特別之處。我們只是創建一個簡單類,同時設置兩個類變量或者說屬性,即cahce與max_cache_size。其中cache屬于一套空字典,而max_cache_size顯然代表著***緩存容量。下面讓我們進一步充實該代碼,使其具備一定功能:
- import datetime
- import random
- ########################################################################
- class MyCache:
- """"""
- #----------------------------------------------------------------------
- def __init__(self):
- """Constructor"""
- self.cache = {}
- self.max_cache_size = 10
- #----------------------------------------------------------------------
- def __contains__(self, key):
- """
- 根據該鍵是否存在于緩存當中返回True或者False
- """
- return key in self.cache
- #----------------------------------------------------------------------
- def update(self, key, value):
- """
- 更新該緩存字典,您可選擇性刪除最早條目
- """
- if key not in self.cache and len(self.cache) >= self.max_cache_size:
- self.remove_oldest()
- self.cache[key] = {'date_accessed': datetime.datetime.now(),
- 'value': value}
- #----------------------------------------------------------------------
- def remove_oldest(self):
- """
- 刪除具備最早訪問日期的輸入數據
- """
- oldest_entry = None
- for key in self.cache:
- if oldest_entry == None:
- oldest_entry = key
- elif self.cache[key]['date_accessed'] < self.cache[oldest_entry][
- 'date_accessed']:
- oldest_entry = key
- self.cache.pop(oldest_entry)
- #----------------------------------------------------------------------
- @property
- def size(self):
- """
- 返回緩存容量大小
- """
- return len(self.cache)
在這里,我們導入了datetime與random模塊,而后我們即可看到之前創建完成的類。這一次,我們向其中添加幾種方法。其中一種方法具備神奇的效果,名為_contains_。雖然在這里并不一定要使用該方法,但其基本思路在于允許我們檢查該類實例,從而了解其中是否包含有我們正在尋找的鍵。另外,update方法負責利用新的鍵/值對進行緩存字典更新。一旦達到或者超出緩存***容量,其還會刪除日期最早的輸入數據。另外,remove_oldest方法負責具體的字典內早期數據刪除工作。***,我們還引入了名為size的屬性,其能夠返回緩存的具體容量。
在添加了以下代碼之后,我們就能夠測試該緩存是否按預期起效:
- if __name__ == '__main__':
- #測試緩存
- keys = ['test', 'red', 'fox', 'fence', 'junk',
- 'other', 'alpha', 'bravo', 'cal', 'devo',
- 'ele']
- s = 'abcdefghijklmnop'
- cache = MyCache()
- for i, key in enumerate(keys):
- if key in cache:
- continue
- else:
- value = ''.join([random.choice(s) for i in range(20)])
- cache.update(key, value)
- print("#%s iterations, #%s cached entries" % (i+1, cache.size))
在本示例當中,我們設置了大量預定義鍵與循環。如果鍵尚不存在,我們會將其添加到緩存當中。不過以上示例代碼并沒有提到如何更新訪問日期,感興趣的朋友們可以將其作為練習自行探索。在運行這段代碼之后,大家會注意到當緩存被占滿時,其會正確刪除時間更早的條目。
現在,我們繼續前進,看看如何利用另一種方式使用Python的內置functools模塊創建緩存。
使用functools.lru_cache
Python的functools模塊提供一種非常實用的裝飾器,即lru_cache。需要注意的是,其在3.2版本當中才被添加進來。根據說明文檔所言,該裝飾器能夠“利用可調用內存對函數進行打包,從而削減最近調用的***尺寸。”接下來,我們將根據說明文檔中提到的示例編寫一項基本功能,其中包含多個網絡頁面。在這種情況下,我們可以直接從Python說明文檔站點處獲取頁面。
- import urllib.error
- import urllib.request
- from functools import lru_cache
- @lru_cache(maxsize=24)
- def get_webpage(module):
- """
- 獲取特定Python模塊網絡頁面
- """
- webpage = "https://docs.python.org/3/library/{}.html".format(module)
- try:
- with urllib.request.urlopen(webpage) as request:
- return request.read()
- except urllib.error.HTTPError:
- return None
- if __name__ == '__main__':
- modules = ['functools', 'collections', 'os', 'sys']
- for module in modules:
- page = get_webpage(module)
- if page:
- print("{} module page found".format(module))
在以上代碼當中,我們利用lru_cache對get_webpage函數進行了裝飾,并將其***尺寸設置為24條調用。在此之后,我們設置了一條網頁字符串變量,并將其傳遞至我們希望函數獲取的模塊當中。根據我的個人經驗,如果大家將其運行在某種Python解釋器當中——例如IDLE——那么效果會更好。如此一來,我們就能夠針對該函數運行多次循環。可以看到在***運行上述代碼時,輸出結果的顯示速度相對比較慢。但如果大家在同一會話中再次加以運行,那么其顯示速度將極大加快——這意味著lru_cache已經正確對該調用進行了緩存處理。大家可以在自己的解釋器實例當中進行試驗并親自查看結果。
另外,我們還可以將一條typed參數傳遞至該裝飾器。其屬于一條Boolean,旨在通知該裝飾器在typed為設定為True時對不同類型參數進行分別緩存。
總結
現在大家已經初步了解了如何利用Python編寫自己的緩存機制。這是一款有趣的工具,而且能夠在各位面對大量高強度I/O調用或者希望對登錄憑證等常用信息進行緩存時發揮重要作用。
原文標題:Python開發:緩存機制介紹
【51CTO譯稿,合作站點轉載請注明原文譯者和出處為51CTO.com】