fbpx

相信在學Python程式語言的朋友都知道,Python語法簡單易學且非常簡潔,今天要來介紹的Comprehension即是Python的Pythonic語法之一,可以運用在任何可疊代的物件(Iterable Object)上,只要一行程式碼即可完成多行的任務,讓我們的程式碼簡潔及增加可讀性。

透過今天的教學,您將可以學到Python Comprehension如何應用在以下幾個重要的物件(Object)上,並且有能力將現有程式碼改寫為Python Comprehension語法。

  • List Comprehension
  • Set & Dictionary Comprehension
  • Generator Expression

 

一、List Comprehension

串列(List)Comprehension的語法包含三個部分,說明如下:
  • expression:可以是 item 或運算式。
  • item:接收可疊代的物件(Iterable Object)元素。
  • iterable:可疊代的物件(Iterable Object)。
通常要建立一個串列(List),我們可以透過for迴圈的方式,如下範例:
執行結果
如果透過串列(List)Comprehension來進行改寫的話,只需要一行即可達到相同的執行結果,如下範例:
x * 3 就是串列(List)Comprehension中的運算式(expression),而 x 是接收可疊代的物件(Iterable Object)變數,最後就是可疊代的物件(Iterable Object) range(10) 。透過for迴圈的方式讀取元素值,並且乘以3來建立串列(List),語法是不是非常簡潔~
如果我們要在串列(List)Comprehension中利用條件判斷來篩選元素時,則可以使用下列語法:
延伸上面的範例,當 x 大於4的時候,我們才乘以3的動作,串列(List)Comprehension的寫法如下範例:
執行結果
另外,串列(List)元素的運算及篩選我們在Python Lambda Function應用技巧分享文章中有介紹到可以利用Python的內建函式map()和filter()等,其中透過了Lambda函式來達成,而串列(List)Comprehension語法同樣也可以實作,我們來比較一下寫法吧。
首先,map()函式可以將特定運算式套用至可疊代的物件(Iterable Object)元素,如下範例:
map()函式利用Lambda函式來進行元素的運算,最後透過list()函式來轉型成串列(List)。而串列(List)Comprehension可以改寫成:
我們再來看一個例子,filter()函式可以幫我們篩選可疊代的物件(Iterable Object)元素,如下範例:
在串列(List)Comprehension中則可以改寫為:
在此範例中,我們將條件判斷擺在後面來篩選可疊代的物件(Iterable Object)元素,那如果要依據條件來“改變”串列(List)中的值時,則要把條件判斷移至前方,如下範例:
範例中透過條件判斷將串列(List)中小於等於10的值修改為0,而大於10的則維持原值。
Python Comprehension語法和Lambda函式一樣,適當的使用可以讓程式碼簡潔且可讀性佳,避免撰寫過於複雜的邏輯,否則只會讓未來維護時不易修改。

二、Set & Dictionary Comprehension

集合(Set)Comprehension的用法和串列(List)Comprehension幾乎一樣,不同的地方是集合(Set)使用 {} 符號,並且其中的元素不會重覆,如下範例:
從範例中可以看到 titles 中符合條件的 e 字母有3個,但是集合(Set)只會顯示1個。
另外,字典(Dictionary)Comprehension和集合(Set)Comprehension同樣使用 {} 符號,不同的是字典(Dictionary)的每個元素由鍵(Key)與值(Value)構成,如下範例:
執行結果
範例中利用enumerate()函式回傳可疊代的物件(Iterable Object)元組(Tuple),再透過Unpacking的方式取得鍵(index)與值(letter) ,詳細的觀念可以參考Python Unpacking實用技巧分享

三、Generator Expression

各位一定會想說,那有元組(Tuple)Comprehension嗎?我們依照上面的原則來撰寫如下範例:
執行結果
從執行結果可以看到,我們得到了一個Generator物件(Object),這是什麼呢?
Generator物件(Object)具有延遲的特性,也就是說它不會把所有資料都儲存在記憶體中,而是透過迴圈進行讀取時,來產生值。所以Generator物件(Object)適用於處理非常龐大的資料集,甚至無限個資料的情況。如果透過串列(List)或元組(Tuple)等其它物件來處理時,會將所有資料都儲存在記憶體中,這時候就可以想像將會耗盡記憶體資源。
假設我們將上面範例中的 range(10) 調整為 range(20000),來模擬要處理的資料集非常龐大,接著引用sys模組中的getsizeof()函式(Function),來取得串列(List)及Generator物件(Oject)各佔用了多少記憶體空間,如下範例:
執行結果
可以看到串列(List)占用了89008Bytes,而Generator物件(Object)只佔用了56Bytes,省下了不少記憶體空間。但是也需要特別注意,由於Generator物件(Object)不像其它物件如串列(List)等,把所有資料都儲存在記憶體中,所以是無法得知Generator物件(Object)的資料個數,如下範例:
執行結果
可以看到我們可以取得串列(List)的資料個數,而無法取得Generator物件(Object)的資料個數。

四、小結

以上就是Python Comprehension語法的介紹,可以看到單行就可以執行許多的任務,非常Pythonic的語法,希望大家有學起來。在練習的過程中如果有碰到任何問題歡迎留言分享。
「好文轉自古耕全–Python Comprehension語法應用教學,如果你喜歡他的文章歡迎回到他的部落格看更多:)」