Python快取技術

公號_python學習開發發表於2018-10-16

一段非常簡單程式碼

普通呼叫方式

def console1(a, b):
    print("進入函式")
    return (a, b)

print(console1(3, 'a'))
print(console1(2, 'b'))
print(console1(3.0, 'a'))
複製程式碼

很簡單的一段程式碼,傳入兩個引數。然後列印輸出。
輸出結果

進入函式
(3, 'a')
進入函式
(2, 'b')
進入函式
(3.0, 'a')
複製程式碼

使用某個裝飾器後

接下來我們引入functools模組的lru_cache,python3自帶模組。

from functools import lru_cache
@lru_cache()
def console2(a, b):
    print("進入函式")
    return (a, b)
print(console2(3, 'a'))
print(console2(2, 'b'))
print(console2(3.0, 'a'))
複製程式碼

ほら、驚喜來了。

進入函式
(3, 'a')
進入函式
(2, 'b')
(3, 'a')
複製程式碼

我們發現,少了一次進入函式的列印,這是怎麼回事呢?
這就是接下來要說的LRU快取技術了。

我們理解下什麼是LRU

LRU (Least Recently Used) 是快取置換策略中的一種常用的演算法。當快取佇列已滿時,新的元素加入佇列時,需要從現有佇列中移除一個元素,LRU 策略就是將最近最少被訪問的元素移除,從而騰出空間給新的元素。

python中的實現

python3中的functools模組的lru_cache實現了這個功能,
lru_cache裝飾器會記錄以往函式執行的結果,實現了備忘
(memoization)功能,避免引數重複時反覆呼叫,達到提高效能的作用,在遞迴函式中作用特別明顯。這是一項優化技術,它把耗時的函式的結果儲存起來,避免傳入相同的引數時重複計算。

帶引數的lru_cache

使用方法lru_cache(maxsize=128, typed=False)
maxsize可以快取最多個此函式的呼叫結果,從而提高程式執行的效率,特別適合於耗時的函式。
引數maxsize為最多快取的次數,如果為None,則無限制,設定為2的n次冪時,效能最佳;
如果 typed=True,則不同引數型別的呼叫將分別快取,例如 f(3) 和 f(3.0),預設False
來一段綜合程式碼:

from functools import lru_cache

def console1(a, b):
    print("進入函式")
    return (a, b)


@lru_cache()
def console2(a, b):
    print("進入函式")
    return (a, b)


@lru_cache(maxsize=256, typed=True)
def console3(a, b):
    '''

    :param a:
    :param b:
    :return:
    '''
    print("進入函式")
    return (a, b)


print(console1(3, 'a'))
print(console1(2, 'b'))
print(console1(3.0, 'a'))
print("*" * 40)
print(console2(3, 'a'))
print(console2(2, 'b'))
print(console2(3.0, 'a'))
print("*" * 40)
print(console3(3, 'a'))
print(console3(2, 'b'))
print(console3(3.0, 'a'))
複製程式碼

同樣的可以用到爬蟲的去重操作上,避免網頁的重複請求。
在後期儲存的時候做判斷即可。

from functools import lru_cache
from  requests_html import HTMLSession
session=HTMLSession()
@lru_cache()
def get_html(url):
    req=session.get(url)
    print(url)
    return req

urllist=["https://www.baidu.com","https://pypi.org/project/pylru/1.0.9/","https://www.baidu.com"]

if __name__ == '__main__':
    for i in urllist:
        print(get_html(i))
複製程式碼

輸出

https://www.baidu.com
<Response [200]>
https://pypi.org/project/pylru/1.0.9/
<Response [200]>
<Response [200]>
複製程式碼

ok,今天的內容就到這裡,趕緊去試一試吧


相關文章