加速函數,每個Python程式設計師都應該了解標準庫的Lru_cache

2020-12-13 51CTO

加速函數,每個Python程式設計師都應該了解標準庫的Lru_cache

Python標準庫附帶了許多鮮為人知但功能強大的軟體包。對於本示例,將使用functools中的lru_cache。(LRU代表「最近最少使用(Least Recently Used)」,正如字面意思,這明確意味著緩存將保留最近的輸入/結果對。)

作者:讀芯術來源:今日頭條|2020-03-22 11:12

加速新境界:通過使用簡單的緩存功能,僅需一行代碼即可加速你的函數。

不久前,我構建了一個日常運行的ETL管道,其通過從外部服務中抽取數據來豐富輸入數據,然後將結果加載到資料庫中。

隨著輸入數據的增加,等待外部伺服器的響應變得非常費時,這使得ETL進程越來越慢。經過一番調查,我發現與總記錄數(~500k)相比,並沒有太多不同的輸入值(~500)。

因此,換句話說,使用相同的參數調用外部服務時,每個參數大約要重複執行1000次。

像這樣的情況是使用緩存的主要用例。緩存一個函數意味著無論何時首次計算函數的返回值,都會將其輸入和結果放在字典中。

對於每個後續函數調用,首先通過查看緩存來檢查結果是否已經計算過。如果在緩存中找到了,那就很完美,不需要再次計算!如果沒有找到,就計算結果並將輸入和結果存儲在緩存中,以便下一個函數調用時查找到它。

Python標準庫附帶了許多鮮為人知但功能強大的軟體包。對於本示例,將使用functools中的lru_cache。(LRU代表「最近最少使用(Least Recently Used)」,正如字面意思,這明確意味著緩存將保留最近的輸入/結果對。)

從Fun(c)tools中導入lru_cache

把c放進括號中有點像一個蹩腳的笑話,因為這樣functools就變成了fun tools(有趣的工具),使用緩存當然很有趣!

這裡無需過多解釋。導入lru_cache並用它來裝飾一個函數,該函數將生成斐波那契數。

裝飾函數意味著將該函數與緩存函數包裝在一起,隨後每當調用fib_cache函數時,都將調用緩存的函數。

比賽開始

我們進行了一個實驗,計算函數的緩存和未緩存版本從0到40計算所有斐波那契數所花費的時間,並將結果放入各自的列表中。

獲勝者

對於較小的斐波那契數,二者並沒有什麼大的區別,但是一旦達到約30個樣本,緩存函數的效率增益就開始累加。

我沒有耐心讓未緩存的版本運行超過40個樣本,因為它的運行時間是指數增長的。而對於緩存的版本,它的運行時間只是線性增量。

這就完成了!距離Python緩存僅一行代碼之遙。畢竟它並沒那麼可怕。

在初始示例中,我在Pandas數據框上使用了數據轉換。值得一提的是,緩存的函數可以傳遞給Pandas apply,而無需進行其它的任何更改。

是不是很棒?你也來試試吧~

【編輯推薦】

【責任編輯:

趙寧寧

TEL:(010)68476606】

點讚 0

相關焦點

  • Python 3.10 都發布了,還需要 Ordered Dict 嗎?
    (集合:等一下,容我想想)以兩個排序不同的 dict 為例,執行結果如下d_1 = dict(a=1, b=2)d_2 = dict(b=2, a=1)print(d_1 == d_2)這是因為在之前的 dict 中 「順序」 是個不存在的概念,自然也就沒有驗證順序的意義只要兩個字典的鍵值對相同
  • 關於Python導入模塊,你可能沒學透?!
    我們來看看在Python中如何實現這點:from functools import lru_cache上面這行代碼可以讓你直接調用 lru_cache。如果你按常規方式導入 functools,那麼你就必須像這樣調用 lru_cache:functools.lru_cache(*args)根據你實際的使用場景,上面的做法可能是更好的。在複雜的代碼庫中,能夠看出某個函數是從哪裡導入的這點很有用的。
  • @程式設計師,Python 3 還有哪些未 Get 的潛藏技能?| 技術頭條
    註:文中的代碼示例基於 Python 3.7 編寫,為方便使用,在每個功能後面都列出了該功能所需的最低 Python 版本。f-strings (3.6+)對任何一種程式語言來說,字符串處理是一項很重要的內容,字符串處理往往是很多程序的基礎部分。
  • python包package和模塊module導入深入詳解
    我們來看看在Python中如何實現這點:from functools import lru_cache上面這行代碼可以讓你直接調用 lru_cache。如果你按常規方式導入 functools,那麼你就必須像這樣調用 lru_cache:functools.lru_cache(*args)根據你實際的使用場景,上面的做法可能是更好的。在複雜的代碼庫中,能夠看出某個函數是從哪裡導入的這點很有用的。不過,如果你的代碼維護的很好,模塊化程度高,那麼只從某個模塊中導入一部分內容也是非常方便和簡潔的。
  • Python的Functools模塊簡介
    functools模塊是Python的標準庫的一部分,它是為高階函數而實現的。高階函數是作用於或返回另一個函數或多個函數的函數。一般來說,對這個模塊而言,任何可調用的對象都可以作為一個函數來處理。我們將@cached_property裝飾器[3]分別應用於這兩個函數,以將它們轉換為緩存屬性。這意味著值確實只計算了一次,然後就被緩存了。備註:DataSet的每個實例都需要有一個帶有不可變映射的__dict__屬性。這是裝飾器能夠正確工作所必需的。
  • 關於import,你應該知道這些內容
    作為一名新手Python程式設計師,你首先需要學習的內容之一就是如何導入模塊或包。但是我注意到,那些許多年來不時使用Python的人並不是都知道Python的導入機制其實非常靈活。import urllib.error這個情況不常見,但是對此有所了解總是沒有壞處的。很多時候你只想要導入一個模塊或庫中的某個部分。我們來看看在Python中如何實現這點:from functools import lru_cache上面這行代碼可以讓你直接調用lru_cache。
  • Python導入模塊的幾種姿勢
    我們來看看在Python中如何實現這點:from functools import lru_cache上面這行代碼可以讓你直接調用lrucache。如果你按常規方式導入functools,那麼你就必須像這樣調用lrucache:functools.lru_cache(*args)根據你實際的使用場景,上面的做法可能是更好的。
  • Python 2.7終結於7個月後,這是你需要了解的3.X炫酷新特性
    在這篇文章中,作者介紹了 3.0 以來真正 Amazing 的新函數與新方法,也許這些方法我們都不太熟,但它們確實在實踐中非常重要。許多人在了解到 Python 2.7 即將停止維護後,都開始將他們的 Python 版本從 2 切換到 3。截止到 5 月 19 號上午 10 點,Python 2.7 將終結於...
  • 5年 Python 功力,總結了 10 個開發技巧
    /site-packages/usr/lib64/python2.7/site-packages/usr/lib64/python2.7/site-packages/gtk-2.0/usr/lib/python2.7/site-packages這裡我要介紹的是比上面兩種都方便得多的方法,一行命令即可解決。
  • 你可能不知道的 Python 技巧
    但是須注意,並非每個系統都支持隱藏密碼。Python 會嘗試警告你,因此切記在命令行中閱讀警告信息。12、查找單詞/字符串的相近匹配現在,關於 Python 標準庫中一些晦澀難懂的特性。如果你發現自己需要使用Levenshtein distance 【2】之類的東西,來查找某些輸入字符串的相似單詞,那麼 Python 的 difflib 會為你提供支持。
  • Python程式設計師最常犯的10個錯誤,你中招了嗎?
    那就是在每次調用函數前沒有對可變參數進行賦值,而認為該參數就是默認值。比如上面的代碼,有人可能期望在反覆調用foo()時返回'baz',以為每次調用foo()時,bar的值都為[],即一個空列表。答案就是,函數參數的默認值僅在定義函數時執行一次。因此,僅在第一次定義foo()時,bar初始化為默認值(即空列表),此後,每次調用foo()函數時,參數bar都是第一次初始化時生成的列表。
  • 新手請進:每個Python程式設計師都應該知道的10個縮寫詞
    學習過程中,我們會逐漸熟悉它的數據結構、控制流、類、函數和其他基本知識。還有一件有趣的事人們不常提起:我們時不時就會遇到Python中的各種首字母縮寫詞。本文將回顧十個這樣的縮寫詞,包括通用的編程原理以及特定的Python編碼,每個詞都有自己有用有趣的方面。1.
  • 代碼跑得慢甩鍋Python?手把手教你如何給代碼提速30%
    由此可見,exp函數是罪魁禍首,現在我們可以更詳細地了解時序和性能分析。時序特定功能現在我們知道了應當主要關注哪裡,我們可能想對運行速度緩慢的函數計時,而不用測量其餘的代碼。時間包提供time.perf_counter和time.process_time兩個函數。他們的區別在於perf_counter返回的絕對值,包括你的Python程序進程未運行時的時間,因此它可能會受到計算機負載的影響。另一方面,process_time僅返回用戶時間(不包括系統時間),這僅是你的過程時間。加速吧!
  • python中的函數增強神器functools模塊
    functools是一個函數增強器,主要為高階函數使用,作用於或者返回其他函數的函數,通常任何可調用的對象都可視為「函數」。
  • Python2 倒計時,還不快來掌握 Python3 酷炫的新特性?|原力計劃
    下面我們從幾個有趣的新特性入手,這些特性或方法都是 Python 3 各個版本中新加的,它們相比傳統的 Python 方法,更容易解決實踐中的一些問題。所有的示例都是在 Python 3.7 的環境下編寫的,每個特性示例都給出了其正常工作所需的最低的 Python 版本。
  • Numba:基於CUDA加速的高性能Python
    導致python如此流行的原因有很多,主要有其簡潔且易於理解的語法和標準的數據結構,廣泛的功能齊備的標準庫,優秀的文檔,庫和工具構成的良好的生態系統,專業支持的可用性以及大而開放的社區。也許最重要的是,像Python這樣的動態類型解釋語言的高效率。Python是靈活的,這使其成為可用於快速原型設計的一種很好的語言,同時也能用於構建完整的系統。
  • 9種你不知道的Python 3功能
    for fruit in Fruit: print(fruit) -> Fruit.APPLE-> Fruit.ORANGE-> Fruit.GUAVA最低要求Python版本:3.42.類型提示相對於動態而言,靜態打字是計算機語言中的熱門話題,每個人對此都有自己的見解。
  • Python 程式設計師最常犯的十個錯誤
    return barPython程式設計師常犯的一個錯誤,就是想當然地認為:在每次調用函數時,如果沒有為可選參數傳入值,那麼這個可選參數就會被設置為指定的默認值。在上面的代碼中,你們可能覺得重複調用foo()函數應該會一直返回'baz',因為你們默認每次foo()函數執行時(沒有指定bar變量的值),bar變量都被設置為[](也就是,一個新的空列表)。
  • Python 標準庫之 JSON
    關於 JSON 更為詳細的內容,可以參考其官方網站,在這我截取部分內容,讓大家更好的了解一下 JSON 的結構。JSON 構建於兩種結構基礎之上:Python 標準庫中有 JSON 模塊,主要是執行序列化和反序列化功能。
  • Python 3中一些不常用但有效的特性
    所有示例均由python 3.8編寫,對於該算法,每一特性都需要最低要求的python版本。f-strings (3.6+)無論使用何種程式語言,如果沒有字符串就很難執行任何操作。如果你希望能夠採用一種結構化的方式來處理字符串以提高生產力,大部分Python用戶傾向於使用format 方法。