Python lambda: 從入門到放棄

2021-03-02 測試不將就

(全文字數: 3000, 閱讀時間: 5分鐘)

Python是我的日常程式語言,公眾號有部分文章會寫我的Python使用心得。去年3月份寫過一篇關於Python lambda的技術文章,雖然在公眾號上閱讀量平平,但是轉載到CSDN博客之後卻火了。累計閱讀量已經接近15萬,並且每天都在持續增加。許多同學也是看了這篇文章才關注我的公眾號或加我好友的。

在文章中,我對Python匿名函數lambda作了"一個語法,三個特性,四個用法"的總結。儘管網絡上關於Python lambda的資料汗牛充棟,但是像那篇文章一樣把它講得透徹和易懂的卻不多。感興趣的同學可以點開看看。在文章末尾,我留下了一個伏筆,提到了在Python社區中,對於是否應該使用lambda是存在爭議的。贊同者有之,反對者亦有之。

一年多以前,我還是lambda的重度使用者,並且在網絡上搖旗吶喊,寫文章幫助大家入門lambda。而現在,隨著經驗的積累和認知的轉變,我想說的是,自己已經在代碼中慢慢放棄使用lambda了。今天,我就給大家講講,為什麼會發生這種180度大轉彎的事情。

我們知道,Python基於lambda的編程具有代碼緊湊和簡潔的優勢。然而,它的不足也是明顯的,那就是可讀性較差。這是因為,lambda定義的是一個沒有名字的函數,因此我們可能無法很容易知道它是幹什麼的。並且,很多時候lambda函數是作為參數傳給另外一個高階函數的,這意味著在一行代碼中會同時出現函數的定義和函數的調用,從而更增加了理解難度。

對於編程來說,代碼編寫的頻率是遠遠小於代碼被閱讀的頻率的。因此代碼的可讀性成為一件至關重要的事情。lambda的弱可讀性,是它的一個硬傷。

接下來,大家會看到,有兩類情況,我們可以放棄lambda,提升代碼可讀性。先說第一類情況:我們可能找到更好的替代品,在保持代碼簡潔性不變的同時,提升代碼的可讀性。下面是一些例子。

lambda的一種用法是與filter函數結合,過濾列表中符合條件的元素。例如將列表[1, 2, 3]中是3的倍數的數字過濾出來的lambda實現為:

filter(lambda x: x % 3 == 0, [1, 2, 3])

這時,我們可以用list comprehension(列表理解)來完成同樣的工作:

[i for i in [1, 2, 3] if i % 3 == 0]

大家可以看到,代碼簡潔性並沒有變化,而可讀性卻明顯提升了。

類似的,lambda常常與map函數結合,針對列表的每一個元素做同樣的某種操作。這種場景也可以用列表理解來替代,以提升可讀性。例如:

map(lambda x: x+1, [1, 2, 3])

將列表[1, 2, 3]中的元素分別加1,其結果[2, 3, 4]。可以被替換為:

[i + 1 for i in [1, 2, 3]]

可見,在一些場景下,使用列表理解能夠替換lambda,在保持代碼簡潔性的同時,提升代碼可讀性,可謂"一石二鳥"。當然,這些情況下我們也可以用生成器表達式(generator expression)來替換lambda,效果與列表理解一致,並且程序性能更優。為了節省篇幅我們這裡不展開,感興趣的同學可以去網上了解下。

繼續舉例。lambda經常與sorted函數結合,針對列表進行排序。某些時候我們也可以放棄lambda。例如,

sorted([1, 3, -2, -4], key=lambda x: abs(x))

針對列表[1, 3, -2, -4],根據元素絕對值大小進行排序,輸出結果是[1, -2, 3, -4]。由於abs是Python內置函數,因此lambda是多此一舉的。類似這種可以直接使用Python內置函數的情況,建議捨棄lambda:

sorted([1, 3, -2, -4], key=abs)

類似的,注意到Python標準庫operator提供了用函數來調用Python操作符的方法。因此,在能夠使用operator提供的操作符函數的地方,也可以捨棄lambda。

例如,下面這個lambda和reduce函數結合使用的例子。獲得列表[2, 3, 4]所有元素的乘積,結果是24:

reduce(lambda x, y: x * y, [2, 3, 4], 1)

基於operator提供的mul函數(等價於*操作符)的替代方案是:

from operator import mulreduce(mul, [2, 3, 4], 1)

operator提供的不只有操作符函數。例如attrgetter函數能夠得到對象的屬性,可以在下面這種情況下替換掉lambda:

sorted(nodes, key=lambda p: p["width"])from operator import attrgettersorted(nodes, key=attrgetter("width"))

以上介紹了如何使用列表理解/生成器表達式/Python內置函數/Python標準庫operator來替換lambda。它們都是不錯的替代品,能夠在保證簡潔性的情況下提升代碼的可讀性。

這是第一類情況。現在看第二類情況,那就是在第一類情況不適用的時候,我們如有必要,還可以犧牲簡潔性來換取代碼可讀性的提升。

例如,下面這個lambda與sorted函數結合的例子:

points = [((1, 2), 'red'), ((3, 4), 'green')]points_by_color = sorted(points, key=lambda p: p[1])

這裡排序的對象是一個元祖列表,排序依據是元祖的索引為1的元素。這段代碼不僅存在hardcode,而且可讀性也差,排序的依據並不清晰。

這時候,我們可以使用def定義一個排序依據函數color_of_point,將其作為參數傳遞給sorted函數。在函數名字和函數文檔字符串(docstring)的輔助下,代碼容易理解多了:

def color_of_point(point):"""Return the color of the given point."""  (x, y), color = point  return color
points = [((1, 2), 'red'), ((3, 4), 'green')]points_by_color = sorted(points, key=color_of_point)

從這個例子可以看到,當lambda函數的含義不直白或者存在hardcode時,可以放棄lambda而定義一個正式的函數。雖然需要多寫幾行代碼,但是可讀性得到提升,投入產出比是好的。

以上就是我總結的關於放棄lambda的兩點建議。一是使用列表理解/生成器表達式/Python內置函數/Python標準庫operator來替換lambda,在保證簡潔性的情況下,提升代碼可讀性。二是定義一個正式的函數,將函數的功能描述清楚,犧牲程序簡潔性,換得可讀性的提升。

這兩點建議應該能夠覆蓋大部分實際情況。在我看來,只有這兩點建議都行不通時,才保留使用lambda。當然,我不認為徹底放棄lambda在現階段是合理的。例如在下面這個依據元素與數字2的距離的大小進行排序的例子中,lambda的價值仍然存在:

sorted([1, 3, -2, -4], key=lambda x: abs(x-2))

最後,歡迎大家留言發表自己對Python lambda的看法。

推薦閱讀:

可能是史上最全Python lambda講解

Python: 告別Print?

相關焦點

  • python入門基礎之lambda匿名函數詳解
    python入門基礎之lambda匿名函數詳解剛開始學習python的時候很多人可能對於lambda函數不了解,感覺和def很混亂,下面我來介紹一下lambda函數我從一下幾個方面來介紹lambda:1、lambda簡介2、lambda與def不同之處3、lambda的使用方法
  • Python中lambda的使用,與它的三個好基友介紹!
    很多朋友說,python入門有推薦的書嗎?其實遇到這種問題,會比較難回答,因為如果一心想學python,現在網絡那麼發達,怎麼都能找到資料學。當然你要真讓我推薦一本書,我還是想說《python學習手冊第四版》,這本書乍一看突出一個厚字,但內容講的是真的很細緻!如果你不知道python學哪本書,還是推薦你看看它。大家可以從我公眾號底部的領取福利中,找到這本書。
  • 詳細講解:python中的lambda與sorted函數
    本文內容主要介紹了python中的lambda與sorted函數的相關資料,幫助大家更好的理解和學習python,感興趣的朋友可以了解下!!!
  • python之lambda函數使用
    二,lambda簡單使用def detail(x,y): return x*ys = lambda x,y:x*yprint(s(3,3))以上對比我們可以看出如果我們想計算兩個數的乘積,需要定義一個函數,傳入兩個形參,然而lambda也是直接傳入兩個形參。後面使用冒號,寫入表達式,即可得到我們所需要的結果。
  • Python每天一分鐘:lambda表達式 (匿名函數)及用法詳解
    lambda表達式介紹python中有一種靈活,便捷的且具有函數功能的表達式:lambda表達式!python lambda表達式如果說函數是命名的、便於復用的代碼塊,那麼lambda 表達式則是功能更靈活的代碼塊,它可以在程序中被傳遞和調用。
  • Python中的lambda函數
    儘管它們在語法上看起來不同,lambda函數的行為方式與使用def關鍵字聲明的一般函數相同。以下是Python中 lambda函數的特點:在本文中,我們將詳細討論Python中的lambda函數,並演示使用它們的例子。
  • Python中的4個Lambda函數示例
    翻譯:老齊與本文相關的圖書推薦:《跟老齊學Python:輕鬆入門》說明: 本書是針對零基礎學習者的入門讀物,書中以深入淺出的方式介紹了Python語言的相關知識。Lambda函數式Python裡的匿名函數,有時候提到匿名函數,就是指Lambda函數,其基本語法是:lambda parameters: expression。這裡用lambda關鍵詞標記我們要定義一個Lambda函數,然後是參數列表,參數的個數可以是0個,或者多個。後面是冒號(英文狀態下),然後就是Lambda函數中的表達式。
  • Python中Lambda的前4個錯誤
    當然,lambda具有使我們的代碼簡潔的優勢,但是在項目中過度使用它們會導致濫用,從而降低我們代碼的可讀性和可維護性。在開始研究這些誤用是什麼之前,讓我們先快速回顧一下lambda。如果您對它們非常了解,則可以跳到下一部分。Lambda,也稱為lambda函數,是匿名函數,可以接受任意數量的參數,而只有一個表達式。它們的聲明由lambda關鍵字表示。
  • 實例中學習python的walk/map/filter/lambda
    從尋找特定文件夾中尋找特定後綴名的文件列表是一個很常用的場景,可以擴展到將找到的(符合條件的)文件列表做重命名、刪除、備份等操作。我們本次就從此實例出發,去學習python語言中的walk/map/filter/lambda函數的使用。
  • python入門
    --Yves Hilpisch 《Python for Finance》發現近期學習python的人越來越多了,最近也有人問我有沒有啥課程或者書推薦的。我自己還是側重數據計算和在金融中的應用,系統管理、web開發等沒做過。我當年也是新手入門,自己搜索嘗試,買了很多的書,也在網上下載了很多資料。
  • 通過「四不要」,掌握 Python 的 Lambda 函數
    譯文出自:掘金翻譯計劃本文永久連結:https://github.com/xitu/gold-miner/blob/master/article/2020/master-python-lambda-functions-with-these-4-donts.md譯者:loststar  校對者:luochen1992Lambda 函數是 Python
  • 如何入門Python之Python基礎教程詳解
    隨著人工智慧的發展,Python近兩年也是大火,越來越多的人加入到Python學習大軍,對於毫無基礎的人該如何入門Python呢?這裡整理了一些個人經驗和Python入門教程供大家參考。如果你是零基礎入門 Python 的話,建議初學者至少達到兩個目標: 會用,理解。
  • Python的一行代碼有何魅力?lambda匿名函數都自嘆不如
    lambda表達式在學習Python的過程中,很多人常常對lambda表達式的語法感到困惑,什麼是lambda?lambda表達式怎麼用,什麼時候該用lambda?請看下去,下面內容將為你介紹。Python中的lambda是用來創建匿名函數,它是一個表達式,但函數體比def簡單,它的語法如下:語法參數中,arg為入口參數,expression為函數體,用函數表達則如下圖所示:用學習函數的方式來學習lambda表達式就非常容易理解了,在這裡lambda簡化了函數定義的書寫形式,使得代碼更簡潔。
  • Python推薦書籍從入門到進階(珍藏版)
    《Python編程:從入門到實踐》本書的講解很到位,不過就是在對一些簡單知識點的講解方面投入了過多的筆墨。書中練習的原始碼下載地址:ehmatthes.github.io/pcc這是英文版的勘誤表【網站:nostarch.com/pythoncras】:
  • python入門教程NO.8 用python寫個存款利息計算器
    本文涉及的python基礎語法為def函數,return,函數的各參數示例,匿名函數等函數初識函數是一段組織好的\ 可重複使用的\ 用來實現特定功能的代碼塊。函數的參數關鍵字參數的應用示例必備參數的應用示例默認參數的應用示例不定長參數的應用示例python 使用 lambda 來創建匿名函數
  • Lambda詳解->C+&py
    貳  再看一下,python中的lambda表達式。python裡的lambda簡單多了,標誌是關鍵字lambda,後面則是    (輸入) :(輸出) lambda argument_list: expression但是在某些情況(build-in內置函數)就是很方便:herolist_json = requests.get
  • Python中的Lambda表達式
    Lambda函數的語法lambda arguments: expressionLambda函數可以具有任意數量的參數,但只能有一個表達式。>def square1(num):return num ** 2print(square(5)) # 輸出: 25在上面的lambda示例中,lambda x: x ** 2產生一個可以與任何名稱關聯的匿名函數對象。
  • Python匿名函數:Lambda表達式
    我們以一張圖形進入主題:從圖中我們可以看出lambda表達式幾點特徵:簡潔性,符合了Python的一貫宗旨;起到了函數的作用,但未顯示函數名稱,這就是匿名函數;有形參;有返回值的。【2】Lambda表達式如何實現函數功能?
  • 史丹福大學教授推薦兩本Python入門書籍
    今天給大家分享自己學習的python的入門書籍。曾經我們讀書的時候,對編程能力特別感興趣,可是我本身發展不是學計算機的,所以進行編程技術只能看視頻通過自學。那時候,我接觸到的第一門語言是C++,就是一個學了很久,但是由於這門藝術語言教育太過深奧,我學了幾個月,連一些企業基本的圖形設計開發也實現不了,後來我果斷放棄使用編程了。在後來偶然因素之間相互接觸了解到python這門專業語言,給我打開了一扇新的大門。因為python實在太簡單了,直接在命令行打」1+1「,回車就出來結果了,交互性也是非常強。
  • 不要在Python中編寫 lambda 表達式了
    lambda 表達式是 Python 中創建匿名函數的一個特殊語法. 我稱 lambda 語法本身為 lambda 表達式, 而它返回的函數我稱之為 lambda 函數.Python 的 lambda 表達式允許在一行代碼中創建一個函數並傳遞(通常傳遞到另外一個函數).