尋找符合Python風(fēng)格的求和方式

本文摘自《流暢的Python》(《FluentPython》)游岳,作者Luciano Ramalho只损,譯者安道 吳珂


=============

序言

就像“什么是美”沒有確切的答案一樣掠械,“什么是Python風(fēng)格”也沒有標(biāo)準(zhǔn)答案微王。如果回答“地道的Python”累提,不能讓人100%滿意判呕,因為對你來說是“地道的”倦踢,在我看來卻可能不是。但我可以肯定的是侠草,“地道”并不是指使用最鮮為人知的語言特性辱挥。

先決條件

  • 歸約函數(shù)(reduce、sum边涕、any晤碘、all)將序列或有限的迭代對象變成一個聚合結(jié)果
  • reduce函數(shù)在目前的更新中已經(jīng)被收進(jìn)functools包中了
  • 函數(shù)簽名reduce(function, iterable, initializer)
    其中第三個參數(shù)initializer是可選的功蜓。它避免了空序列拋出異常园爷,如果令了這個參數(shù),將從這個參數(shù)開始式撼。(一般為恒等值童社,如+|^等令為1,+ &令為0)端衰。
    function是一個接收兩個參數(shù)的函數(shù)叠洗。
  • 調(diào)用的一般過程為:如序列[1,2,3,4,5]
    fun(1,2) (=a)
    fun(a, 3) (=b)
    fun(b, 4) etc...

問題提出

Python-list上有一篇題為“Pythonic Way to Sum n-th List Element?”(鏈接似已失效?)的話題與本篇討論的reduce函數(shù)有關(guān)旅东。
該話題發(fā)起人Guy Middleton說他不喜歡使用lambda表達(dá)式,問如下方案可否改進(jìn):

>>>my_list = [[1, 2, 3], [40, 50, 60], [9, 8, 7]]
>>>import functools
>>>functools.reduce(lambda a,, b: a+b, [sub[1] for sub in my_list])
60

這段代碼包含了:lambda十艾、reduce和列表推導(dǎo)抵代。這對于討厭lambda和看不上列表推導(dǎo)的人兩邊不討好——這兩種人都很多。如果使用lambda忘嫉,或許就不應(yīng)該使用列表推導(dǎo)——過濾除外荤牍,但這不是過濾((for x in list if x > 0) 其中if就是過濾表達(dá)式)案腺。


=============

本書的作者給出的方案是:

>>> functools.reduce(lambda a, b: a + b[1], my_list, 0)
60

但作者表示不會在真實代碼如此寫,(因為他也不喜歡lambda表達(dá)式)康吵。此處僅僅是為了舉例說明不使用列表推導(dǎo)怎么做劈榨。


=============

第一個答案

,來自Fernando Perez晦嵌,IPython的創(chuàng)建者同辣,強(qiáng)調(diào)了NumPy支持n維數(shù)組和n維切片:

>>> import numpy as np
>>>my_array = np.array(my_list)
>>>np.sum(my_array[:, 1]
60

(即一維全體,二維的下標(biāo)1元素)


=============

第二個答案

惭载,Guy Middleton推崇Paul Rubin和Skip Montanaro給出的下述方案:

>>> import operator
>>> functools.reduce(operator.add, my_list, 0)
60

其中旱函,operator庫中包含諸如add, xor等常用數(shù)字運算函數(shù),包含兩個參數(shù)


=============

以及

描滔,EvanSimpson問道:"這樣做有什么錯棒妨?"

>>> total = 0
>>> for sub in my_list:
...            total += sub[1]
>>>total
60

foreach循環(huán)。
許多人都覺得這也很符合Python風(fēng)格含长。Alex Martelli甚至說券腔,Guido或許就會這么做。
作者喜歡這段代碼拘泞,更喜歡David Eppstein對此給出的評論:

如果你想計算列表各個元素的和颅眶,寫出的代碼應(yīng)該看起來像是在“計算元素之和”,而不是“迭代元素田弥,維護(hù)一個變量t涛酗,再執(zhí)行一系列求和操作”。如果不能站在一定高度上表明意圖偷厦,讓語言去關(guān)注低層次操作商叹,那么要高級語言干嘛?

之后Alex Martelli又建議:

求和操作經(jīng)常需要只泼,我不介意Python提供一個這樣的內(nèi)置函數(shù)剖笙。但是,在我看來请唱,“reduce(operator..add,...”不是好方法(作為一名APL老程序員和FP語言的愛好者弥咪,我應(yīng)該喜歡,但我并不喜歡)十绑。


隨后

Alex建議提供并實現(xiàn)了sum()函數(shù)并在之后的Python2.3中內(nèi)置了聚至。因此,Alex喜歡的句法變成了標(biāo)準(zhǔn):(列表推導(dǎo)本橙,僅能生成list)

>>> sum([sub[1] for sub in my_list])
60

下一年年末(2004年11月)扳躬,Python2.4發(fā)布,這一版引入了生成器表達(dá)式。因此贷币,作者建議击胜,當(dāng)前這個問題最符合Python風(fēng)格的答案是:(生成任何類型的序列)

>>> sum(sub[1] for sub in my_list)
60

這樣寫不僅比reduce函數(shù)可讀性更強(qiáng),而且還避免了空序列導(dǎo)致的陷阱:sum([])的結(jié)果是0役纹,就這么簡單
在這次討論中偶摔,Alex Martelli指出,Python2內(nèi)置的reduce函數(shù)成事不足敗事有余促脉,因為他推薦的地道編程方式難以理解辰斋。他的觀點最優(yōu)說服力:Python3把reduce函數(shù)移到functools模塊中了。

end

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嘲叔,一起剝皮案震驚了整個濱河市亡呵,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌硫戈,老刑警劉巖锰什,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異丁逝,居然都是意外死亡汁胆,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進(jìn)店門霜幼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嫩码,“玉大人,你說我怎么就攤上這事罪既≈猓” “怎么了?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵琢感,是天一觀的道長丢间。 經(jīng)常有香客問我,道長驹针,這世上最難降的妖魔是什么烘挫? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮柬甥,結(jié)果婚禮上饮六,老公的妹妹穿的比我還像新娘。我一直安慰自己苛蒲,他們只是感情好卤橄,可當(dāng)我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著撤防,像睡著了一般虽风。 火紅的嫁衣襯著肌膚如雪棒口。 梳的紋絲不亂的頭發(fā)上寄月,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天辜膝,我揣著相機(jī)與錄音,去河邊找鬼漾肮。 笑死厂抖,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的克懊。 我是一名探鬼主播忱辅,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼谭溉!你這毒婦竟也來了墙懂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤扮念,失蹤者是張志新(化名)和其女友劉穎损搬,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體柜与,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡巧勤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了弄匕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片颅悉。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖迁匠,靈堂內(nèi)的尸體忽然破棺而出剩瓶,到底是詐尸還是另有隱情,我是刑警寧澤城丧,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布延曙,位于F島的核電站,受9級特大地震影響芙贫,放射性物質(zhì)發(fā)生泄漏搂鲫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一磺平、第九天 我趴在偏房一處隱蔽的房頂上張望魂仍。 院中可真熱鬧,春花似錦拣挪、人聲如沸擦酌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽赊舶。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間笼平,已是汗流浹背园骆。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留寓调,地道東北人锌唾。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像夺英,于是被迫代替她去往敵國和親晌涕。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內(nèi)容