Python 列表生成式與 if 條件的完整解說!條件過濾與進階技巧

目次

1. 前言

Python 的「列表生成式(List Comprehension)」是一種用來簡潔建立列表的便利語法。相較於使用一般的 for 迴圈來建立列表,這種寫法在程式碼可讀性與執行效率上都有明顯優勢。

特別是當列表生成式搭配 if 條件語句時,可以只篩選出符合條件的元素,讓列表操作更具彈性。本文將從基礎到進階,搭配實用範例,詳盡介紹如何在 Python 中結合列表生成式與 if 條件語句。

什麼是列表生成式?

列表生成式是一種能讓你簡潔撰寫 Python 列表的語法。相比傳統的 for 迴圈,它可以讓你用更少的程式碼撰寫出更易讀的邏輯。

例如,如果你想建立一個從 0 到 4 的整數列表,使用傳統的 for 迴圈寫法如下:

2. Python 列表生成式的基礎

在前一節中,我們介紹了什麼是列表生成式以及它的優點。本節將進一步說明列表生成式的基本語法,並透過具體範例幫助你更深入理解。

列表生成式的基本語法

列表生成式的基本語法如下:

[運算式 for 變數 in 可疊代物件]

語法組成說明

  • 運算式:針對變數進行的處理(例如計算或函數)
  • for 變數 in 可疊代物件:從可疊代物件(如列表、元組、range 等)中逐一取出元素的迴圈

例如,要建立一個包含從 0 到 4 整數的列表,使用傳統 for 迴圈會像這樣:

numbers = []
for i in range(5):
    numbers.append(i)
print(numbers)  # [0, 1, 2, 3, 4]

但使用列表生成式時,只需要一行就能完成:

numbers = [i for i in range(5)]
print(numbers)  # [0, 1, 2, 3, 4]

列表生成式的基本範例

透過列表生成式,我們可以更簡潔地進行列表建立與轉換。以下是幾個常見的基本應用:

1. 將每個元素平方

以下是將 0 到 9 的整數平方後存入列表的範例:

squares = [i**2 for i in range(10)]
print(squares)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

使用傳統 for 迴圈的寫法如下:

squares = []
for i in range(10):
    squares.append(i**2)
print(squares)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

2. 轉換字串列表

將字串列表中的所有字串轉為大寫:

words = ["python", "list", "comprehension"]
uppercase_words = [word.upper() for word in words]
print(uppercase_words)  # ['PYTHON', 'LIST', 'COMPREHENSION']

傳統寫法如下:

words = ["python", "list", "comprehension"]
uppercase_words = []
for word in words:
    uppercase_words.append(word.upper())
print(uppercase_words)  # ['PYTHON', 'LIST', 'COMPREHENSION']

3. 扁平化列表(將巢狀列表展開)

當我們想將二維列表轉為一維列表時,也可以使用列表生成式:

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row]
print(flattened)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

使用傳統寫法則如下:

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = []
for row in matrix:
    for num in row:
        flattened.append(num)
print(flattened)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

透過列表生成式,即使是巢狀迴圈也能用簡潔的一行來實現。

3. 搭配 if 條件的列表生成式

在上一節中,我們學習了列表生成式的基本用法。從這裡開始,我們將說明如何將 if 條件語句結合到列表生成式中,建立具條件篩選的列表。

透過在列表生成式中加入 if,可以輕鬆過濾出符合特定條件的元素,讓列表建立更具彈性與效率。

if 條件的列表生成式基本語法

若想根據條件建立列表,基本語法如下:

[運算式 for 變數 in 可疊代物件 if 條件]

語法說明

  • 運算式:對每個元素所執行的操作
  • for 變數 in 可疊代物件:對可疊代物件(如列表、元組、range 等)進行的迴圈
  • if 條件:僅當條件為真時,該元素才會加入列表

基本使用範例

1. 篩選偶數

例如,我們要從 0 到 9 的整數中,挑出偶數並加入列表:

evens = []
for i in range(10):
    if i % 2 == 0:
        evens.append(i)
print(evens)  # [0, 2, 4, 6, 8]

使用列表生成式則更簡潔:

evens = [i for i in range(10) if i % 2 == 0]
print(evens)  # [0, 2, 4, 6, 8]

→ 將 if 寫入列表生成式中,可以省略 append(),讓程式碼更短更易讀。

2. 過濾字串列表

你也可以使用列表生成式,從字串列表中篩選符合條件的元素:

例如,從 ["python", "java", "c++", "ruby"] 中,選出字數 5 個以上的程式語言:

languages = ["python", "java", "c++", "ruby"]
long_languages = [lang for lang in languages if len(lang) >= 5]
print(long_languages)  # ['python']

3. 抽取包含特定字元的單字

若要從列表中篩選包含某特定字母的單字,也可以用列表生成式來達成。

以下是範例,抽取包含 "a" 的單字:

words = ["apple", "banana", "cherry", "date"]
words_with_a = [word for word in words if "a" in word]
print(words_with_a)  # ['apple', 'banana', 'date']

如何指定多個條件

if 條件中,你可以使用 andor 來組合多個條件。

1. 抽出同時為偶數且為 3 的倍數的數字

filtered_numbers = [i for i in range(20) if i % 2 == 0 and i % 3 == 0]
print(filtered_numbers)  # [0, 6, 12, 18]

2. 過濾同時符合多條件的字串

words = ["python", "java", "c++", "ruby", "go", "haskell"]
filtered_words = [word for word in words if len(word) >= 5 and "o" in word]
print(filtered_words)  # ['python']

常見錯誤與解法

1. if 的位置錯誤

錯誤示範(if 放在錯誤的位置)

numbers = [if i % 2 == 0 for i in range(10)]

錯誤訊息:SyntaxError: invalid syntax

正確寫法

numbers = [i for i in range(10) if i % 2 == 0]

2. 錯誤使用 and / or

錯誤示範

words = ["apple", "banana", "cherry"]
filtered_words = [word for word in words if len(word) > 5 or "a" in word]

若想同時滿足多個條件,請使用 and

filtered_words = [word for word in words if len(word) > 5 and "a" in word]

小結

  • 在列表生成式中加入 if,可以根據條件篩選元素
  • 語法為:[運算式 for 變數 in 可疊代物件 if 條件]
  • 可用於篩選偶數、字串過濾等各種場景
  • 支援 and / or 多條件組合
  • 注意 if 的位置與條件語法,避免語法錯誤

4. 使用 if-else 的列表生成式

在上一節中,我們學會了如何使用 if 來篩選符合條件的元素。不過,如果你想根據條件來決定不同的值加入列表,就需要搭配 if-else 一起使用。

本節將說明如何撰寫含有 if-else 的列表生成式,並提供實用範例幫助你理解其應用。

if-else 列表生成式的基本語法

若要在列表生成式中加入 if-else 條件,其語法如下:

[值1 if 條件 else 值2 for 變數 in 可疊代物件]

語法說明

  • 值1:當條件成立時,要加入列表的值
  • 條件if 所判斷的條件
  • else 值2:當條件不成立時,要加入的值
  • for 變數 in 可疊代物件:遍歷可疊代物件的迴圈

注意:當使用 if-else 時,if 要寫在 for 的前面!
→ 如果只用 if,它會寫在 for 的後面;但 if-else 時,必須寫在前面。

基本範例

1. 偶數保持原樣,奇數改為 “odd”

以下範例將 0 到 9 的整數中,偶數保持原值,奇數改成字串 “odd”:

numbers = []
for i in range(10):
    if i % 2 == 0:
        numbers.append(i)
    else:
        numbers.append("odd")
print(numbers)  
# [0, 'odd', 2, 'odd', 4, 'odd', 6, 'odd', 8, 'odd']

使用列表生成式則只需一行:

numbers = [i if i % 2 == 0 else "odd" for i in range(10)]
print(numbers)  
# [0, 'odd', 2, 'odd', 4, 'odd', 6, 'odd', 8, 'odd']

→ 透過 if-else,你可以根據條件靈活地轉換每個元素的值。

2. 將小於等於 0 的數值轉為 “negative”

假設我們有一個包含正負數值的列表,要將小於等於 0 的值替換為 “negative”:

numbers = [-5, 3, 0, 8, -2, 7]
modified_numbers = [num if num > 0 else "negative" for num in numbers]
print(modified_numbers)  
# ['negative', 3, 'negative', 8, 'negative', 7]

3. 根據正負數進行分類

將數值分類為 “positive” 或 “negative” 的例子如下:

numbers = [-10, 15, 0, -5, 20]
categories = ["positive" if num > 0 else "negative" for num in numbers]
print(categories)  
# ['negative', 'positive', 'negative', 'negative', 'positive']

使用 if-else 時的注意事項

1. if 的位置要正確

錯誤寫法(會出現語法錯誤)

numbers = [i for i in range(10) if i % 2 == 0 else "odd"]

錯誤訊息:SyntaxError: invalid syntax

正確寫法

numbers = [i if i % 2 == 0 else "odd" for i in range(10)]

👉 要記得:if-else 要放在 for 前面!

2. ifif-else 的差異

  • 只用 if:用來過濾元素
evens = [i for i in range(10) if i % 2 == 0]
print(evens)  # [0, 2, 4, 6, 8]

→ 條件不符合的元素會被排除。

  • 使用 if-else:根據條件轉換每個值
numbers = [i if i % 2 == 0 else "odd" for i in range(10)]
print(numbers)  
# [0, 'odd', 2, 'odd', 4, 'odd', 6, 'odd', 8, 'odd']

→ 所有元素都會加入列表,只是依據條件決定值的內容。

小結

  • 使用 if-else 可以根據條件決定不同的值加入列表
  • if-else 必須寫在 for 的前面
  • 與只用 if 的列表生成式不同,if-else 不會排除任何元素
  • 適合用於數值分類、字串替換等場合
  • 也可以使用巢狀 if-else 來應對多條件判斷

5. 巢狀列表生成式與條件判斷

在上一節中,我們學習了如何使用 if-else 進行條件處理。本節將介紹如何使用 巢狀列表生成式(多重迴圈的列表生成式)

列表生成式就像傳統 for 迴圈一樣,也可以使用 巢狀迴圈。這讓我們可以更有效率地處理二維列表(例如列表中的列表)。

巢狀列表生成式的基本語法

要在列表生成式中使用多重迴圈,其基本語法如下:

[運算式 for 變數1 in 可疊代物件1 for 變數2 in 可疊代物件2]

語法說明

  • 運算式:針對變數進行的操作
  • for 變數1 in 可疊代物件1:外層迴圈
  • for 變數2 in 可疊代物件2:內層迴圈

重點是:執行順序是從左到右,和一般的巢狀迴圈邏輯一致。

基本範例

1. 將二維列表「扁平化」

假設我們有一個二維列表,想將其轉換為一維列表,可以這樣做:

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = []
for row in matrix:
    for num in row:
        flattened.append(num)
print(flattened)  
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

使用列表生成式就能一行完成:

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row]
print(flattened)  
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

→ 巢狀列表生成式能讓你用更簡潔的方式處理巢狀結構的資料。

2. 建立所有組合

例如,我們想將 A, B, C1, 2, 3 組成所有可能的組合:

letters = ["A", "B", "C"]
numbers = [1, 2, 3]
combinations = []

for letter in letters:
    for number in numbers:
        combinations.append(f"{letter}{number}")

print(combinations)  
# ['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']

使用列表生成式的寫法如下:

letters = ["A", "B", "C"]
numbers = [1, 2, 3]
combinations = [f"{letter}{number}" for letter in letters for number in numbers]

print(combinations)  
# ['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']

使用巢狀列表生成式可以將多重迴圈壓縮成簡潔的一行

結合條件判斷

在巢狀列表生成式中,也可以搭配 ifif-else 來進行條件篩選或值的轉換。

3. 篩選總和為偶數的數字對

1~34~6 中,找出「總和為偶數」的數字對:

list1 = [1, 2, 3]
list2 = [4, 5, 6]
pairs = []

for x in list1:
    for y in list2:
        if (x + y) % 2 == 0:
            pairs.append((x, y))

print(pairs)  
# [(1, 5), (2, 4), (2, 6), (3, 5)]

使用巢狀列表生成式可以寫得更簡潔:

list1 = [1, 2, 3]
list2 = [4, 5, 6]
pairs = [(x, y) for x in list1 for y in list2 if (x + y) % 2 == 0]

print(pairs)  
# [(1, 5), (2, 4), (2, 6), (3, 5)]

使用巢狀列表生成式的注意事項

1. 可讀性容易下降

  • 巢狀太深時可讀性會變差,請避免過度使用
  • 若可讀性為首要考量,建議改用傳統 for 迴圈

2. 注意 if 的位置

  • 只使用 if 時 → 寫在 for 的後面
  • 使用 if-else 時 → 寫在 for 的前面

3. 巢狀太深時,考慮拆成函數

  • 當邏輯變得太複雜時,與其硬寫成一行列表生成式,不如改用函數來提高可讀性

小結

  • 巢狀列表生成式可以簡化二維資料的處理與多重迴圈邏輯
  • 可以結合 if 條件來篩選符合條件的項目
  • 也可以使用 if-else 根據條件設定不同的值
  • 但巢狀過深會影響可讀性,請依情況選擇是否使用

6. 列表生成式的最佳實踐與注意事項

列表生成式是 Python 中非常方便的功能,可以讓你用更簡潔的方式撰寫程式碼。但若使用不當,可能會導致可讀性變差或效能下降。
本節將說明 如何正確使用列表生成式的最佳實踐與常見注意事項

適合使用列表生成式的情境

以下是幾個適合使用列表生成式的情境:

1. 簡單的列表建立

當你只是要進行簡單的元素轉換或建立列表時,使用列表生成式是非常合適的。

範例:將每個元素平方

squares = [x**2 for x in range(10)]
print(squares)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

2. 條件過濾(篩選元素)

當你需要從列表中篩選出符合特定條件的項目時,列表生成式非常適合。

範例:過濾出偶數

evens = [x for x in range(10) if x % 2 == 0]
print(evens)  # [0, 2, 4, 6, 8]

3. 字串列表轉換

列表生成式在處理字串列表的轉換時也非常實用。

範例:將字串轉成大寫

words = ["python", "list", "comprehension"]
uppercase_words = [word.upper() for word in words]
print(uppercase_words)  # ['PYTHON', 'LIST', 'COMPREHENSION']

4. 扁平化巢狀列表

當你需要將二維列表轉換成一維列表 時,列表生成式可以大幅簡化寫法。

範例:將二維列表展平成一維列表

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row]
print(flattened)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

不適合使用列表生成式的情況

以下是使用列表生成式時應避免的情況:

1. 巢狀過深,導致可讀性差

列表生成式雖然簡潔,但若巢狀太深,可讀性會明顯下降

❌ 不佳範例:三層巢狀迴圈

matrix = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
flattened = [num for row in matrix for subrow in row for num in subrow]

👉 太難閱讀,不容易維護

✅ 建議改寫為傳統 for 迴圈:

flattened = []
for row in matrix:
    for subrow in row:
        for num in subrow:
            flattened.append(num)

2. 處理邏輯太長,導致程式碼混亂

列表生成式的優勢在於簡潔的一行式寫法若條件過於複雜反而會造成混亂

❌ 不佳範例:條件與運算太多

numbers = [x**2 if x % 2 == 0 else x**3 for x in range(10) if x != 5 and x % 3 != 0]

✅ 建議使用傳統寫法來提升可讀性:

numbers = []
for x in range(10):
    if x != 5 and x % 3 != 0:
        if x % 2 == 0:
            numbers.append(x**2)
        else:
            numbers.append(x**3)

列表生成式的效能表現

1. 比 for 迴圈更快

列表生成式通常比傳統的 for 迴圈執行得更快,因為 Python 會對其進行內部最佳化

效能比較範例:

import time

data = list(range(10**6))

# 使用列表生成式
start = time.time()
squares = [x**2 for x in data]
print("列表生成式:", time.time() - start)

# 使用傳統 for 迴圈
start = time.time()
squares = []
for x in data:
    squares.append(x**2)
print("傳統 for 迴圈:", time.time() - start)
  • 列表生成式通常能快上 30%~50%
  • 但會一次性佔用大量記憶體

2. 若需節省記憶體,可使用生成器表達式

當資料量龐大時,建議使用 生成器(generator expression) 來取代列表生成式。

# 列表生成式(耗記憶體)
squares = [x**2 for x in range(10**6)]

# 生成器表達式(省記憶體)
squares_gen = (x**2 for x in range(10**6))

squares_gen 不會立即建立整個列表,而是逐一產生值,節省記憶體。

小結

適合使用列表生成式的情況

  • 簡單的列表建立
  • 條件過濾
  • 字串轉換
  • 扁平化二維列表

不建議使用的情況

  • 巢狀太深的處理
  • 條件或運算過於複雜
  • 影響可讀性的長行程式碼

💡 最佳實踐

  • 簡單邏輯請使用列表生成式
  • 複雜邏輯請用傳統 for 迴圈
  • 根據效能與可讀性選擇正確的寫法
年収訴求

7. 常見問題(FAQ)

在本節中,我們將解答有關 列表生成式的常見疑問,並說明實際開發時應注意的重點。這些問題包含新手常犯錯誤與效能上的疑慮。

Q1. 可以在列表生成式中使用兩次 if 嗎?

A1. 可以,但需注意可讀性。

在列表生成式中,if 可以寫兩次以上,達到多重條件的篩選效果。

範例:篩選同時為偶數且為 3 的倍數的數字

filtered_numbers = [x for x in range(30) if x % 2 == 0 if x % 3 == 0]
print(filtered_numbers)  # [0, 6, 12, 18, 24]

這種寫法效果就像「AND 條件」。但從可讀性角度來看,使用 and 會更清楚

filtered_numbers = [x for x in range(30) if x % 2 == 0 and x % 3 == 0]

Q2. 列表生成式和傳統 for 迴圈,該用哪一個?

A2. 根據邏輯的簡單程度與可讀性選擇最適合的方式。

如果處理邏輯 簡單明確,列表生成式非常實用;但若邏輯 複雜多層,傳統迴圈會比較清楚易懂。

範例:建議用傳統 for 迴圈的情況

# ❌ 難以閱讀的列表生成式
numbers = ["Even" if x % 2 == 0 else "Odd" if x % 3 == 0 else "Other" for x in range(10)]

# ✅ 傳統寫法更清楚
numbers = []
for x in range(10):
    if x % 2 == 0:
        numbers.append("Even")
    elif x % 3 == 0:
        numbers.append("Odd")
    else:
        numbers.append("Other")

Q3. ifif-else 的用途有什麼不同?

A3. if 用於篩選,if-else 用於值的轉換。

✅ 僅使用 if:只留下符合條件的元素

evens = [x for x in range(10) if x % 2 == 0]
print(evens)  # [0, 2, 4, 6, 8]

→ 不符合條件的項目會被排除。

✅ 使用 if-else:保留所有元素,但根據條件轉換值

labels = ["even" if x % 2 == 0 else "odd" for x in range(10)]
print(labels)  
# ['even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd']

Q4. 列表生成式真的比 for 迴圈快嗎?

A4. 一般來說是的,但記憶體使用量會較高。

Python 的列表生成式因為有內部優化,通常會比 for 迴圈快

⏳ 實測範例:處理 100 萬筆資料

import time

data = list(range(10**6))

# 使用列表生成式
start = time.time()
squares = [x**2 for x in data]
print("列表生成式:", time.time() - start)

# 使用 for 迴圈
start = time.time()
squares = []
for x in data:
    squares.append(x**2)
print("for 迴圈:", time.time() - start)
  • 列表生成式通常快上 30~50%
  • 但會一次載入整個列表,占用較多記憶體

💡 解法:使用生成器(generator expression)
若處理大量資料時想節省記憶體,請改用生成器:

squares_gen = (x**2 for x in data)  # 使用 () 創建生成器

Q5. 除了 listsetdict 也能用內涵式嗎?

A5. 當然可以!Python 也支援 setdict 內涵式。

set(集合)內涵式範例:

unique_squares = {x**2 for x in range(10)}
print(unique_squares)

dict(字典)內涵式範例:

squares_dict = {x: x**2 for x in range(10)}
print(squares_dict)

小結

  • 可使用兩次 if,但建議使用 and 提高可讀性
  • if 用於篩選元素,if-else 用於值的轉換
  • 列表生成式通常比 for 快,但會占用較多記憶體
  • setdict 也支援內涵式語法

以上就是 Python 中有關列表生成式與 if 組合的完整說明!🎉
歡迎你實際動手寫程式,加深理解,真正掌握這項強大的語法技巧!🚀