天天看點

《Python Cookbook(第3版)中文版》——1.2 從任意長度的可疊代對象中分解元素

本節書摘來自異步社群《python cookbook(第3版)中文版》一書中的第1章,第1.2節,作者[美]david beazley , brian k.jones,陳舸 譯,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。

需要從某個可疊代對象中分解出n個元素,但是這個可疊代對象的長度可能超過n,這會導緻出現“分解的值過多(too many values to unpack)”的異常。

python的“表達式”可以用來解決這個問題。例如,假設開設了一門課程,并決定在期末的作業成績中去掉第一個和最後一個,隻對中間剩下的成績做平均分統計。如果隻有4個成績,也許可以簡單地将4個都分解出來,但是如果有24個呢?表達式使這一切都變得簡單:

另一個用例是假設有一些使用者記錄,記錄由姓名和電子郵件位址組成,後面跟着任意數量的電話号碼。則可以像這樣分解記錄:

不管需要分解出多少個電話号碼(甚至沒有電話号碼),變量phone_numbers都一直是清單,而這是毫無意義的。如此一來,對于任何用到了變量phone_numbers的代碼都不必對它可能不是一個清單的情況負責,或者額外做任何形式的類型檢查。

由*修飾的變量也可以位于清單的第一個位置。例如,比方說用一系列的值來代表公司過去8個季度的銷售額。如果想對最近一個季度的銷售額同前7個季度的平均值做比較,可以這麼做:

從python解釋器的角度來看,這個操作是這樣的:

對于分解未知或任意長度的可疊代對象,這種擴充的分解操作可謂是量身定做的工具。通常,這類可疊代對象中會有一些已知的元件或模式(例如,元素1之後的所有内容都是電話号碼),利用*表達式分解可疊代對象使得開發者能夠輕松利用這些模式,而不必在可疊代對象中做複雜花哨的操作才能得到相關的元素。

*式的文法在疊代一個變長的元組序列時尤其有用。例如,假設有一個帶标記的元組序列:

當和某些特定的字元串處理操作相結合,比如做拆分(splitting)操作時,這種*式的文法所支援的分解操作也非常有用。例如:

有時候可能想分解出某些值然後丢棄它們。在分解的時候,不能隻是指定一個單獨的*,但是可以使用幾個常用來表示待丢棄值的變量名,比如_或者ign(ignored)。例如:

*分解操作和各種函數式語言中的清單處理功能有着一定的相似性。例如,如果有一個清單,可以像下面這樣輕松将其分解為頭部和尾部:

在編寫執行這類拆分功能的函數時,人們可以假設這是為了實作某種精巧的遞歸算法。例如:

但是請注意,遞歸真的不算是python的強項,這是因為其内在的遞歸限制所緻。是以,最後一個例子在實踐中沒太大的意義,隻不過是一點學術上的好奇罷了。