# 一次了解 Python Comprehension 的用法 ![chris-ried-ieic5Tq8YMk-unsplash](https://hackmd.io/_uploads/Sy0W6-KDA.jpg) > *Photo by Chris Ried on [Unsplash](https://unsplash.com/photos/a-computer-screen-with-a-bunch-of-code-on-it-ieic5Tq8YMk)* 今天是要來推薦各位讀者老爺們一個有趣的Python小工具,就是 comprehension 啦~ Python 的 comprehension 是一種簡潔且優雅的方式來建立列表、集合、字典和生成器。理解和掌握 comprehension 可以讓你的代碼更簡潔且具可讀性。本文將詳細介紹列表推導式、集合推導式、字典推導式和生成器推導式。 ## 列表推導式 (List Comprehension) 列表推導式用於建立新的列表,語法非常簡潔。基本語法如下: ```python [expression for item in iterable if condition] ``` * **expression** 是應用於每個項目的表達式。 * **item** 是從 **iterable** 中取出的每個元素。 * **condition** 是可選的,它過濾掉那些不滿足條件的元素。 ### 範例 1. 建立一個 **1** 到 **10** 的列表 ```python squares = [item for item in range(1, 11)] print(squares) # 輸出: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] ``` 2. 建立一個只包含偶數的列表 ```python even_squares = [item for item in range(1, 11) if item % 2 == 0] print(even_squares) # 輸出: [2, 4, 6, 8, 10] ``` ## 集合推導式 (Set Comprehension) 集合推導式的語法與列表推導式類似,只是使用大括號 **{}**。它用於建立集合,集合中的元素是唯一的。 ```python {expression for item in iterable if condition} ``` ### 範例 1. 建立一個包含唯一平方數的集合: ```python unique_squares = {x**2 for x in range(10)} print(unique_squares) # 輸出: {0, 1, 64, 4, 36, 9, 16, 81, 49, 25} ``` ## 字典推導式 (Dictionary Comprehension) 字典推導式用於建立字典,語法如下: ```python {key: value for item in iterable if condition} ``` * **key** 和 **value** 是應用於每個項目的表達式。 ### 範例 1. 建立一個數字及其平方的字典: ```python! squares_dict = {x: x**2 for x in range(10)} print(squares_dict) # 輸出: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81} ``` 2. 建立一個只包含偶數及其平方的字典: ```python even_squares_dict = {x: x**2 for x in range(10) if x % 2 == 0} print(even_squares_dict) # 輸出: {0: 0, 2: 4, 4: 16, 6: 36, 8: 64} ``` ## 生成器推導式 (Generator Expression) 生成器推導式用於建立生成器,語法與列表推導式類似,只是使用小括號 **()**。生成器不會立即生成所有元素,而是根據需要逐個生成,這對於處理大量數據非常有用。 ```python (expression for item in iterable if condition) ``` ### 範例 1. 建立一個生成器,生成平方數: ```python squares_generator = (x**2 for x in range(10)) for square in squares_generator: print(square) # 輸出: 0, 1, 4, 9, 16, 25, 36, 49, 64, 81 ``` ### 綜合練習題 讓我們綜合使用不同的 comprehension 來解決一個複雜的問題。假設我們有一個包含學生姓名和成績的列表,我們希望建立一個字典,鍵是學生的姓名,值是他們的成績,並且只包含成績大於 75 的學生。 ```python students = [('Alice', 85), ('Bob', 70), ('Charlie', 90), ('David', 65)] # 使用字典推導式 passed_students = {name: score for name, score in students if score > 75} print(passed_students) # 輸出: {'Alice': 85, 'Charlie': 90} ``` ## 關鍵內容 List Comprehension vs. Generator Expression Generator Expression 是個很特別的東西,這邊特別拿來與 List Comprehension 做比較。 ### 基本概念 * **List Comprehension (列表推導式)**: * 用於建立列表的簡潔語法。 * 會立即生成並儲存所有元素 * **Generator Expression (生成器推導式)**: * 用於建立生成器的簡潔語法。 * 不會立即生成所有元素,而是根據需要逐個生成元素。 ### 記憶體使用 * **List Comprehension**: * 會立即建立並儲存整個列表,這意味著它會佔用與列表大小成正比的記憶體。 * 如果列表非常大,則會消耗大量記憶體,可能導致記憶體不足。 ```python squares_list = [x**2 for x in range(1000000)] ``` 在這個範例中,**squares_list** 會立即包含 1,000,000 個平方數,佔用大量記憶體。 * **Generator Expression**: * 只會在需要時生成每個元素,因此只佔用很少的記憶體。 * 非常適合處理大型數據集或需要逐個處理元素的情況。 ```python squares_generator = (x**2 for x in range(1000000)) ``` 在這個範例中,**squares_generator** 不會立即生成所有平方數,而是根據需要逐個生成,佔用的記憶體非常少。 ### 執行效率 * **List Comprehension**: * 因為列表已經全部生成,所以對列表進行遍歷或操作會更快。 * 適合需要多次訪問或操作列表元素的情況。 * **Generator Expression**: * 因為元素是逐個生成的,所以第一次遍歷生成器會比列表慢。 * 適合一次性生成和處理元素的情況,不適合需要多次遍歷的情況。 ### 記憶體使用測試 ```python import sys # 使用列表推導式建立一個包含 1,000,000 個元素的列表 squares_list = [x**2 for x in range(1000000)] # 列表大小 print(f"列表大小: {sys.getsizeof(squares_list)} bytes") # 使用生成器推導式建立一個包含 1,000,000 個元素的生成器 squares_generator = (x**2 for x in range(1000000)) # 生成器大小 print(f"生成器大小: {sys.getsizeof(squares_generator)} bytes") ``` 輸出結果會顯示列表和生成器在記憶體使用上的巨大差異: ![image](https://hackmd.io/_uploads/SyUvOGYD0.png) 從這裡可以看出,生成器推導式佔用的記憶體非常少,而列表推導式會佔用大量的記憶體。 ### 結論 * **列表推導式** 適合在記憶體充裕且需要多次訪問或操作整個數據集的情況下使用。 * **生成器推導式** 適合在處理大型數據集且需要逐個生成和處理元素的情況下使用,特別是當記憶體資源有限時。 ## 結語 理解和掌握 Python 的 comprehension 語法可以讓你的程式碼更加簡潔和具可讀性。列表推導式、集合推導式、字典推導式和生成器推導式各有其應用場景,熟練運用這些技巧將大大提升你的 coding 效率。 希望這篇文章對觀眾老爺有幫助!如果有任何問題或建議,歡迎在評論區留言。