Python緩存lru_cache的介紹和講解

      網友投稿 1089 2022-05-29

      一、前言

      我們經常談論的緩存一詞,更多的類似于將硬盤中的數據存放到內存中以至于提高讀取速度,比如常說的redis,就經常用來做數據的緩存。

      Python的緩存(lru_cache)是一種裝飾在被執行的函數上,將其執行的結果緩存起來,當下次請求的時候,如果請求該函數的傳參未變則直接返回緩存起來的結果而不再執行函數的一種緩存裝飾器。

      那它和redis的區別在哪?有什么優勢?怎么使用? 下面為你講解

      @TOC

      二、舉例說明

      1.現在我們先不使用緩存來寫一個求兩數之和的函數,并調用執行它兩次:

      def test(a, b): print('開始計算a+b的值...') return a + b print('1+2等于:', test(1, 2)) print('1+2等于:', test(1, 2))

      執行結果

      開始計算a+b的值... 1+2等于: 3 開始計算a+b的值... 1+2等于: 3

      可以看到test被執行了兩次,現在我們加上緩存再進行執行:

      from functools import lru_cache @lru_cache def test(a, b): print('開始計算a+b的值...') return a + b print(test(1, 2)) print(test(1, 2))

      執行結果

      開始計算a+b的值... 1+2等于: 3 1+2等于: 3

      可以看到test函數只被執行了一次,第二次的調用直接輸出了結果,使用了緩存起來的值。

      2.當我們使用遞歸求斐波拉契數列 (斐波那契數列指的是這樣一個數列:0,1,1,2,3,5,8,它從第3項開始,每一項都等于前兩項之和) 的時候,緩存對性能的提升就尤其明顯了:

      不使用緩存求第40項的斐波拉契數列

      import datetime def fibonacci(num): # 不使用緩存時,會重復執行函數 return num if num < 2 else fibonacci(num - 1) + fibonacci(num - 2) start = datetime.datetime.now() print(fibonacci(40)) end = datetime.datetime.now() print('執行時間', end - start)

      執行時間

      執行時間 0:00:29.004424

      使用緩存求第40項的斐波拉契數列:

      @lru_cache def fibonacci(num): # 不使用緩存時,會重復執行函數 return num if num < 2 else fibonacci(num - 1) + fibonacci(num - 2)

      執行時間

      執行時間 0:00:00

      兩個差距是非常明顯的,因為不使用緩存時,相當于要重復執行了很多的函數,而使用了lru_cache則把之前執行的函數結果已經緩存了起來,就不需要再次執行了。

      三、lru_cache 用法

      1.參數詳解

      查看lru_cache源碼會發現它可以傳遞兩個參數:maxsize、typed:

      def lru_cache(maxsize=128, typed=False): """Least-recently-used cache decorator. If *maxsize* is set to None, the LRU features are disabled and the cache can grow without bound. ... """

      1) maxsize

      代表被lru_cache裝飾的方法最大可緩存的結果數量 (被裝飾方法傳參不同一樣,則結果不一樣;如果傳參一樣則為同一個結果), 如果不指定傳參則默認值為128,表示最多緩存128個返回結果,當達到了128個時,有新的結果要保存時,則會刪除最舊的那個結果。如果maxsize傳入為None則表示可以緩存無限個結果;

      2)typed

      默認為false,代表不區分數據類型,如果設置為True,則會區分傳參類型進行緩存,官方是這樣描述的:

      如果typed為True,則將分別緩存不同類型的參數,

      例如,f(3.0)和f(3)將被視為具有明顯的結果。

      但在python3.9.8版本下進行測試,typed為false時,按照官方的測試方法測試得到的還是會被當成不同的結果處理,這個時候typed為false還是為true都會區別緩存,這與官方文檔的描述存在差異:

      from functools import lru_cache @lru_cache def test(a): print('函數被調用了...') return a print(test(1.0)) print(test(1))

      執行結果

      函數被調用了... 1.0 函數被調用了... 1

      但如果是多參數的情況下,則會被當成一個結果:

      from functools import lru_cache @lru_cache def test(a, b): print('函數被調用了...') return a , b print(test(1.0, 2.0)) print(test(1, 2))

      執行結果

      函數被調用了... (1.0, 2.0) (1.0, 2.0)

      這個時候設置typed為true時,則會區別緩存:

      from functools import lru_cache @lru_cache(typed=True) def test(a, b): print('函數被調用了...') return a , b print(test(1.0, 2.0)) print(test(1, 2))

      執行結果

      函數被調用了... (1.0, 2.0) 函數被調用了... (1, 2)

      當傳參個數大于1時,才符合官方的說法,不清楚是不是官方舉例有誤

      2. lru_cache不支持可變參數

      當傳遞的參數是dict、list等的可變參數時,lru_cache是不支持的,會報錯:

      Python緩存lru_cache的介紹和講解

      from functools import lru_cache @lru_cache def test(a): print('函數被執行了...') return a print(test({'a':1}))

      報錯結果

      TypeError: unhashable type: 'dict'

      四、lru_cache 與redis的區別

      五、總結

      經過上面的分析,lru_cache 功能相對于redis來說要簡單許多,但使用起來更加方便,適用于小型的單體應用。如果涉及的緩存的數據種類比較多并且想更好的管理緩存、或者需要緩存數據有過期時間(類似登錄驗證的token)等,使用redis是由于lru_cache的。

      Python

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:Linux系列:文件權限管理、打包和壓縮!
      下一篇:Java基礎之常用類
      相關文章
      亚洲永久中文字幕在线| 亚洲中文字幕AV每天更新| 亚洲AV日韩AV高潮无码专区| 国产亚洲AV夜间福利香蕉149| 亚洲欧美熟妇综合久久久久 | 亚洲精品91在线| 久久综合九九亚洲一区| 亚洲国产精品一区| 亚洲国产精品久久| 亚洲国产一区二区三区青草影视| 亚洲福利视频一区二区| 亚洲AV无码成H人在线观看| 亚洲AV无码乱码在线观看牲色| 亚洲精品久久无码| 国产精品观看在线亚洲人成网| 亚洲 自拍 另类小说综合图区 | www.亚洲一区| 亚洲人成无码www久久久| 亚洲精品无码成人片在线观看| 亚洲一区二区高清| 国产亚洲av片在线观看播放| 亚洲日本一区二区一本一道| 亚洲VA综合VA国产产VA中| 国产亚洲精品bv在线观看| 亚洲欧美日韩中文无线码| 亚洲中文精品久久久久久不卡| 久久久久久亚洲精品影院| 亚洲国产精品ⅴa在线观看| 日韩欧美亚洲中文乱码| 国产成人综合久久精品亚洲| 久久久久久A亚洲欧洲AV冫| 亚洲成A∨人片在线观看不卡| 国产av无码专区亚洲av桃花庵 | 无码乱人伦一区二区亚洲| 国产成人精品日本亚洲| 亚洲三级电影网址| 亚洲午夜在线播放| 日本亚洲中午字幕乱码| 久久久久国产成人精品亚洲午夜| 久久精品国产亚洲| 亚洲一区电影在线观看|