為什么Python 之父如何嫌棄 lambda 匿名函數?

這種便捷的函數定義方式哗总,如果翻譯成我們熟知的函數形式几颜,會是這個樣子:

也就是說,Python 中的 lambda 函數是可以接收多個參數的函數讯屈,返回值是一個表達式蛋哭。

它最大的好處是單行簡潔,不需要函數命名與換行縮進涮母。

不得不說谆趾,匿名函數有時候是挺好用的,比如下文會介紹到的一些常見用法叛本,它因此受到了不少人的推崇沪蓬。

但是,匿名函數通常也會造成代碼難以閱讀来候,容易被人濫用跷叉,再加上 Python 只提供了對它的“殘疾的”支持,所以又有一些觀點不建議使用匿名函數吠勘。

現實上性芬,Python 之父Guido van Rossum就屬于“不推薦使用派”,只不過最后妥協了剧防,他甚至曾經(2005年)想要移除lambda植锉。

lambda 這一個由其他開發(fā)者貢獻進來的特性(借鑒自 lisp 語言),存在了十多年峭拘,但是卻被這門語言的創(chuàng)造者(兼首席設計師)所嫌棄俊庇,最后竟然還奇跡般地幸存了下來狮暑,對于這個故事,大家是否覺得挺有戲劇性的辉饱?

https://jq.qq.com/?_wv=1027&k=f1pgUXkM

接下來搬男,本文就仔細聊一聊這個處境尷尬卻生命力頑強的 lambda 匿名函數吧!

1彭沼、lambda如何使用缔逛?

lambda 函數通常的用法是結合 map()、reduce()姓惑、filter()褐奴、sorted() 等函數一起使用,這些函數的共性是:都可以接收其它函數作為參數于毙。

例如下面的幾個例子:

初學者也許會覺得代碼讀不懂敦冬,但是只要記住“Python中的函數是一等公民”,知道一個函數可以被作為另一個函數的參數或者返回值唯沮,就容易理解了脖旱。

比如對于 map() 函數的例子,你可以理解成這個形式:


甚至可以還原成普通的函數:


map() 函數的第一個參數是一個函數介蛉,第二個參數是一個可迭代對象萌庆。這第一個參數會迭代地調用第二個參數中的元素,調用的結果以迭代器的形式返回甘耿。

這個例子使用了 list()踊兜,是為了方便一次性取出迭代器中的元素,直觀地展示出來佳恬,在實際使用中,很可能會是基于迭代器的形式于游。

以上幾種用法毁葱,我們可以總結出 lambda 函數的使用規(guī)律:

它出現在需要使用函數的地方

它一般不會被獨立使用,總是作為其它函數的一部分

它適合實現簡單的功能

它是一次性的用途贰剥,不能在其它地方復用

2倾剿、lambda 有什么問題?

由上面的用法可以看出蚌成,使用 lambda 函數的代碼比較緊湊簡潔前痘,所以有人稱它體現了“Pythonic”的優(yōu)雅思想。

但是担忧,lambda 函數就沒有什么缺陷嗎芹缔?

有!當前的 lambda 函數有一個最大的問題瓶盛,即只支持單行表達式最欠,無法實現豐富的功能示罗,例如無法在函數創(chuàng)建時使用語句(statement),無法使用 if-else 的判斷條件芝硬,也無法使用 try-except 的異常捕獲機制蚜点,等等。

這極大地限制了它的能力拌阴,導致了它被人詬病為“殘疾的”绍绘。

從技術實現的角度上看,這個問題可以通過語法層面的設計來解決迟赃。

在當年的郵件組討論中陪拘,有人提出過一些解決思路,比如這封郵件:

它提出了一個lambda args::suite的想法捺氢,支持寫成這樣的形式:

但是藻丢,Guido 很快就否決了這個思路。

寫了一篇文章《Language Design Is Not Just Solving Puzzles》來回應:

其基本觀點是:不能光顧著解決一個問題/實現某種功能摄乒,就引入缺乏“Pythonicity”的語言設計悠反。

那么,為什么 Guido 會認為這一種是不好的設計呢馍佑?

我嘗試著概括一下斋否,理由是:

雙冒號“::”憑空在此引入,但是跟切片語法中的“::”完全不同拭荤,而且跟 C++/Perl 中的作用域操作符用法也不同

在 lambda 中實現其它功能并不重要茵臭,這還會讓解析器變得復雜(需區(qū)分是否有縮進、記錄縮進級別)舅世,顯得小題大做了

即使不用雙冒號旦委,用其它符號表示(比如單冒號),還是難以接受雏亚,因為都會在一個表達式中嵌入縮進代碼塊缨硝。這就跟使用花括號和 begin/end 關鍵字來作語句分組(statement grouping)一樣,都令人難以接受

簡而言之罢低,他認為簡潔友好的用戶體驗更為重要查辩,如果簡潔的語法無法滿足需求,就應該寫成具名函數的形式网持,而非設計出復雜的匿名函數宜岛。

3、為什么 Guido 特想移除 lambda功舀?

上文提到的多行 lambda 語句(multi-statement lambda)事件發(fā)生在 2006 年萍倡,我們看到了 Guido 不想給 lambda 引入復雜設計的原因。

但是日杈,早在 2005 年遣铝,Guido 就曾經想要從 Python 移除 lambda佑刷,他對它的“嫌棄”是一個“歷史悠久”的傳統……

在《The fate of reduce() in Python 3000》這篇短文中,Guido 提出要一次性移除 reduce()酿炸、map()瘫絮、filter() 以及 lambda。

移除 lambda理由如下:

很多人誤以為匿名函數能做嵌套函數不能做的事填硕,但其實并無區(qū)別麦萤;存在lambda,就會造成不必要的選擇扁眯,減少選擇壮莹,可以簡化思維

移除 reduce()、map() 和 filter() 后姻檀,就沒必要寫簡短的局部函數了

回顧一下我們在前文中總結出的 lambda 的 4 條使用規(guī)律命满,可以發(fā)現它跟幾個高階函數(可以接收其它函數作為參數的函數)有較強的“寄生關系”,如果它們能移除了的話绣版,lambda 確實就沒有什么獨立存留的意義了胶台。

那么,為什么 Guido 覺得應該移除那幾個高階函數呢杂抽?

主要的理由有:

可以替換成更加清晰的列表解析式或者生成器表達式诈唬,例如 filter(P,S) 可以寫成 [x for x in S if P(x)],map(F, S) 寫成 [F(x) for x in S]

至于 reduce()缩麸,他說這是最討厭的铸磅,除了涉及 + 和 * 的少數用法,其它時候他總要拿出紙筆來畫圖解才能搞清楚杭朱。除了顯式地寫循環(huán)阅仔,他還針對 reduce() 的幾種用法而提出了幾個替代用法,包括引入新的 any() 和 all() 函數

總體而言弧械,Guido 的想法暗合了《The Zen of Python》中的這一條:There should be one-- and preferably only one --obvious way to do it霎槐。

但是回到現實,為了照顧某些人的習慣梦谜,以及對兼容性的考慮,Guido 最后保守地放棄了“清理異端”的計劃袭景。

因此唁桩,lambda 得以從 Python 最高獨裁者的手上死里逃生。直到一年后耸棒,它試圖興風作浪(多行表達式)荒澡,卻慘遭鎮(zhèn)壓。

我仿佛聽到了 Guido 的內心 OS:當初我想刪除東西的時候与殃,你們百般阻撓单山,現在你們卻想添加東西碍现,哼,沒門米奸!……


哈哈昼接,是開了個玩笑。

Guido 的所有決定都體現了他的 Pythonic 設計美學悴晰、自恰的邏輯一致性以及對社區(qū)聲音的權衡慢睡。

對于 lambda,我認可他的觀點铡溪,我覺得 Python 的理解變得更為豐富了漂辐。不知道你們是何感想?

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末棕硫,一起剝皮案震驚了整個濱河市髓涯,隨后出現的幾起案子,更是在濱河造成了極大的恐慌哈扮,老刑警劉巖纬纪,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異灶泵,居然都是意外死亡育八,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門赦邻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來髓棋,“玉大人,你說我怎么就攤上這事惶洲“瓷” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵恬吕,是天一觀的道長签则。 經常有香客問我,道長铐料,這世上最難降的妖魔是什么渐裂? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮钠惩,結果婚禮上柒凉,老公的妹妹穿的比我還像新娘。我一直安慰自己篓跛,他們只是感情好膝捞,可當我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著愧沟,像睡著了一般蔬咬。 火紅的嫁衣襯著肌膚如雪鲤遥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天林艘,我揣著相機與錄音盖奈,去河邊找鬼。 笑死北启,一個胖子當著我的面吹牛卜朗,可吹牛的內容都是我干的。 我是一名探鬼主播咕村,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼场钉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了懈涛?” 一聲冷哼從身側響起逛万,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎批钠,沒想到半個月后宇植,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡埋心,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年指郁,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拷呆。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡闲坎,死狀恐怖,靈堂內的尸體忽然破棺而出茬斧,到底是詐尸還是另有隱情腰懂,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布项秉,位于F島的核電站绣溜,受9級特大地震影響,放射性物質發(fā)生泄漏娄蔼。R本人自食惡果不足惜怖喻,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望岁诉。 院中可真熱鬧罢防,春花似錦、人聲如沸唉侄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽属划。三九已至恬叹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間同眯,已是汗流浹背绽昼。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留须蜗,地道東北人硅确。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像明肮,于是被迫代替她去往敵國和親菱农。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內容