本文 AI 產出,尚未審核

Python 資料結構:清單(list)之 List Comprehension


簡介

在 Python 中,list comprehension(清單生成式)是一種既簡潔又具表達力的語法,讓我們可以在單行程式碼內完成 迭代、條件篩選與結果組合。對於剛踏入程式設計的學員而言,掌握這項技巧不僅能減少重複的 for 迴圈,還能讓程式碼更具可讀性與維護性。

在日常開發中,從資料清理、數值運算到字串處理,幾乎每個需要「把舊資料轉成新資料」的情境,都能使用 list comprehension 以 Pythonic 的方式完成。了解其底層運作原理與常見陷阱,才能在實務上安全、有效地運用這項功能。


核心概念

1. 基本語法

最簡單的 list comprehension 形式如下:

new_list = [expression for item in iterable]
  • iterable:任何可迭代的物件(如 listrangestrdict 等)。
  • item:迭代過程中每一次取得的元素。
  • expression:對 item 進行運算或轉換後產生的值,會依序放入 new_list

範例 1:把 1~5 的整數平方

squares = [x**2 for x in range(1, 6)]
print(squares)   # [1, 4, 9, 16, 25]

這段程式碼等價於

squares = []
for x in range(1, 6):
    squares.append(x**2)

2. 加入條件篩選

for 後面可以加入 if,只把符合條件的元素加入結果:

new_list = [expression for item in iterable if condition]

範例 2:篩選出 1~20 中的偶數

evens = [n for n in range(1, 21) if n % 2 == 0]
print(evens)   # [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

3. 多層迭代(巢狀迴圈)

list comprehension 也支援多個 for,常用於 矩陣展開笛卡爾積

new_list = [expr for x in iterable1 for y in iterable2 if condition]

範例 3:產生 3x3 的座標對

coords = [(i, j) for i in range(3) for j in range(3)]
print(coords)
# [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]

加入條件只保留 i != j 的座標:

diag_removed = [(i, j) for i in range(3) for j in range(3) if i != j]
print(diag_removed)
# [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)]

4. 產生字典或集合

雖然名稱是 list comprehension,但相同的語法也可以產生 集合(set)字典(dict)

# set comprehension
unique_squares = {x**2 for x in [-2, -1, 0, 1, 2]}
print(unique_squares)   # {0, 1, 4}

# dict comprehension
char_cnt = {c: s.count(c) for c in set(s)}

範例 4:統計字串中每個字母出現次數

sentence = "Python is awesome"
freq = {ch: sentence.count(ch) for ch in set(sentence) if ch != ' '}
print(freq)
# {'a': 1, 'e': 2, 's': 2, 'w': 1, 'm': 1, 'P': 1, 'i': 1, 'o': 1, 't': 1, 'n': 1, 'h': 1, 'y': 1}

5. 使用函式或 lambda

expression 中可以直接呼叫函式,或使用 lambda 產生匿名函式,讓程式碼更具彈性:

def square(x):
    return x * x

squares = [square(x) for x in range(5)]
print(squares)   # [0, 1, 4, 9, 16]

範例 5:使用 lambda 把字串轉成大寫

words = ["python", "list", "comprehension"]
upper = [(lambda s: s.upper())(w) for w in words]
print(upper)   # ['PYTHON', 'LIST', 'COMPREHENSION']

常見陷阱與最佳實踐

陷阱 說明 建議的寫法
過度複雜的表達式 一行寫入太多運算或條件,會降低可讀性。 若超過兩層 if 或運算過長,改寫成普通 for 迴圈或拆成小函式。
記憶體消耗 List comprehension 會一次性產生完整列表,對大資料集會佔用大量記憶體。 使用 generator expression(expr for ...))配合 list()itertools,僅在需要時才產生元素。
變數遮蔽 在 comprehension 中使用與外部同名的變數,會在內部覆寫。 盡量避免與外層作用域同名,或使用 _ 作為不需要的迭代變數。
誤用 if-else if-else 必須寫在 expression 前,否則會被解讀成條件篩選。 正確寫法:[a if cond else b for x in iterable],錯誤寫法:[a for x in iterable if cond else b]
嵌套太深 超過三層以上的巢狀迭代,程式碼可讀性急速下降。 使用 itertools.product 或分段產生中間結果。

最佳實踐

  1. 保持單一目的:每個 list comprehension 應該只完成「產生」或「篩選」其中一件事。
  2. 使用說明性變數名稱num, char, row 等,比 x, y 更易理解。
  3. 結合 enumeratezip:可同時取得索引或多個序列的對應元素。
# 例:把字串列表轉成 (index, upper) 元組
items = ["apple", "banana", "cherry"]
result = [(i, s.upper()) for i, s in enumerate(items)]
print(result)   # [(0, 'APPLE'), (1, 'BANANA'), (2, 'CHERRY')]

實際應用場景

  1. 資料清理

    • 從 CSV 讀入的字串欄位需要去除空白、轉成數字或過濾缺失值,list comprehension 可一次完成。
    raw = [" 12 ", " 7", "", "  5 "]
    cleaned = [int(x.strip()) for x in raw if x.strip().isdigit()]
    print(cleaned)   # [12, 7, 5]
    
  2. 特徵工程

    • 在機器學習前,常需把類別特徵轉成 one‑hot 向量,list comprehension 讓向量化操作更直觀。
    colors = ["red", "green", "blue", "red"]
    unique = sorted(set(colors))
    one_hot = [[1 if c == col else 0 for col in unique] for c in colors]
    print(one_hot)
    # [[1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 0, 0]]
    
  3. API 回傳資料的重新構造

    • 取得外部 API 回傳的 JSON 列表後,需要挑出特定欄位並組成新的字典列表。
    users = [
        {"id": 1, "name": "Alice", "age": 28},
        {"id": 2, "name": "Bob", "age": 34},
        {"id": 3, "name": "Cathy", "age": 22},
    ]
    # 只保留 id 與 name
    simple = [{"id": u["id"], "name": u["name"]} for u in users]
    print(simple)
    
  4. 圖形與視覺化

    • 產生座標點或顏色映射,用於 Matplotlib、Plotly 等繪圖套件。
    import matplotlib.pyplot as plt
    xs = [x for x in range(-10, 11)]
    ys = [x**2 for x in xs]          # y = x^2
    plt.plot(xs, ys)
    plt.show()
    

總結

List comprehension 是 Python 中 最具威力且易學 的語法之一。它讓我們能在 單行程式碼 中完成 迭代、條件篩選與資料轉換,大幅提升開發效率與程式可讀性。

  • 了解基本結構 [expr for item in iterable],再逐步加入 if、多層 for,以及 set / dict 生成式。
  • 注意避免過度複雜、記憶體浪費與變數遮蔽等常見陷阱,遵循「單一目的」與「說明性變數」的最佳實踐。
  • 在資料清理、特徵工程、API 整理、圖形繪製等實務情境中,list comprehension 幾乎是 不二選擇

掌握這項技巧後,你將能寫出更 Pythonic、更 簡潔、也更 易於維護 的程式碼。祝你在 Python 的旅程中,玩得開心、寫得順手!