跳到主要內容區塊

計資中心電子報C&INC E-paper

技術論壇

Python小技巧:list comprehensions
  • 卷期:v0071
  • 出版日期:2024-12-20

作者:周秉誼 / Tomofun 資深技術經理


List comprehensions是一個Python提供的語法結構,可以讓程式開發人員用更精簡、更有效率的方式從一個list,產生出另一個list。在Python中除了list之外,comprehension的語法,還可以用在dict和set等資料結構的生成。如果使用得當可以大幅簡化程式碼,增進可讀性,更可能提升程式的運算效能。

前言

Python是非常容易學習的程式語言,不只可以運用在日常工作的自動化、作為網路服務的後端(Backend)程式,語法也十分容易閱讀及理解,相同功能的程式碼通常會有多種不同的表達方式,選擇適當語法改寫之後,可以大幅提升程式碼的可讀性和執行效率。

List comprehensions就是一個Python提供的語法結構,可以讓程式開發人員用更精簡、更有效率的方式從一個list,產生出另一個list。除了list之外,這樣的語法在Python中,還可以用在dict和set等資料結構的生成。

 

list comprehension歷史

list comprehension的概念並不是Python所獨創的,在1970年代的程式語言中,就可以看到類似的概念和語法,並在1980年代之後影響了包括Haskell在內的Functional programming程式語言。list comprehension的語法是由數學上用來建構集合的set-builder表達式所衍伸而來,而set-builder表達式最明顯的特徵就是頭尾的兩個大括號(curly brackets)所組成,在兩個大括號之間指明變數(variable)和條件(condiction),就可以描述一個集合了。

 

list comprehension語法

在Python中的list comprehension,是在2000年時的PEP 202中提出來的。配合Python語言中list的表達式是以中括號(square brackets)來描述,所以Python中list comprehension的頭尾是由中括號組成,在兩個中括號之間包括了三個部份,輸出(output)、資料容器(collection)、及條件(condiction)。使用list comprehension的語法就可以產生出一個list。輸出部份是由一個表達式(Expression)所組成,用來表達生成的list中各個元素的內容,可以是簡單的數學運算或是函式呼叫(function call)的回傳值(return value)。資料容器部份一定會由for關鍵字從某個資料容器或生成函式(generator)中取出各個元素來進行條件判斷和輸出的計算。條件部份是選擇性的,如果資料容器中的每個元素都要放進生成的list,則可以省略條件的部份。

20241220_007107_01

圖1. Comprehension語法及範例

list comprehension優點

在Python中使用list comprehension,主要有兩個好處,第一個是程式碼可以變得較為簡潔,使得可讀性提高;另外在需要產生list的情境之下,使用list comprehension的程式運作效率會比使用for loop及list的append()函式來得好,因為list comprehension會使用更低階的bytecode指令來建造新的list,而for loop版本的append()函式呼叫會花費更高的計算成本。在某種程度上,list comprehension的功能就像是map()和filter()函式的綜合體,可以在一個表達式中同時完成map()及filter()函式的功能。

以常見的排序演算法Quick Sort為例,使用list comprehension的語法可以讓程式變得十分簡潔。Quick Sort中,將陣列中的元素以pivot為準分為大於和小於的兩群是相當麻煩的,然而使用list comprehension產生兩個新的list分別存放,雖然付出了額外的比較計算和記憶體空間,但整體可讀性大為提升了。

list comprehension也可以用來產生巢狀(nested)list,這個功能在生成二維陣列的時候非常好用。在同一個list comprehension的大括號之間,也可以放進多個資料容器進行多層的巢狀處理,資料的索引(index)會由較後面的資料容器先開始變動。除了list comprehension之外,Python在2.7以上的版本也提供了dict comprehension及set comprehension,只是將頭尾的大括號換成dict及set資料結構表達式中的大括號,其中一樣是分為輸出、資料容器、及條件等三個部份。

20241220_007107_02

圖2. 使用For loop及list comprehension範例

 

20241220_007107_03

圖3. Quick Sort使用list comprehension範例

 

20241220_007107_04

圖4. 使用list comprehension產生巢狀list

 

20241220_007107_05

圖5. 使用list comprehension對兩個資料容器進行處理

 

結語

list comprehension在Python程式開發上,是非常好用的語法,如果使用得當可以大幅簡化程式碼,增進可讀性,更可能提升程式的運算效能。在Python中最常使用的三種資料結構list、dict、及set都可以使用相對應的comprehension語法,也讓comprehension的實用性更高。只是comprehension的強頂在於要生成新的資料容器,如果只是要對list中的每一個元素進行處理、但不需要將結果儲存時,使用comprehension就不見得是最好的選擇。

 

參考資料

  • https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions
  • https://peps.python.org/pep-0202/