用 Python 進行迴圈處理的完整指南|從 for 迴圈到 itertools 全面解析

目次

1. 前言

在 Python 中進行反覆處理(迴圈)是提升程式效率與可讀性的重要技巧。多數程式語言中都有稱為 foreach 的語法,可以輕鬆地處理序列中的每個元素;但在 Python 中並沒有直接的 foreach 迴圈。取而代之的,是透過 for 迴圈、enumeratezip 等多種方法來達成類似的功能。本文將從實用且簡潔的角度,說明如何在 Python 中實現類似 foreach 的反覆處理方式。

為什麼 Python 沒有 foreach

Python 沒有明確使用 foreach,是因為該語言強調簡潔與彈性。透過 for 迴圈與內涵表達式(comprehensions),就能輕鬆實作大多數的反覆處理。此外,Python 還提供了許多可以同時取得索引與多個序列元素的方法,使得不需要 foreach 也能輕鬆處理資料。

使用 Python 進行反覆處理的優點

在 Python 中使用迴圈進行處理,有以下幾個主要優點:

  • 簡潔易讀:相較於其他語言,Python 的程式碼較為簡潔,提升可讀性。
  • 靈活性高:可用於多種序列資料類型,如串列、字典、集合等。
  • 內涵表達式:能簡單產生列表或字典,寫出更高效的程式。

下一章我們將深入介紹 Python 中最基礎的反覆處理方式 —— for 迴圈。

2. Python 中 for 迴圈的基本用法

for 迴圈是 Python 中最常見的反覆處理語法,用來逐一處理序列中的元素,例如串列或元組等。以下將詳細說明 for 迴圈的基本使用方式。

for 迴圈的基本語法

Python 的 for 迴圈語法如下:

for 元素 in 序列:
    處理
  • 元素:每次迴圈時會取得序列中的一個值並賦給這個變數。
  • 序列:可以是串列、元組、字串等可反覆處理的資料結構。

範例1:遍歷串列

以下是使用串列與 for 迴圈的基本範例:

fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(fruit)

上述程式碼中,每次迴圈會將 fruits 串列中的元素指定給 fruit,並執行 print(fruit),輸出結果如下:

apple
banana
cherry

範例2:遍歷字串

字串在 Python 中也被視為序列,因此可以逐字處理。

text = "hello"
for char in text:
    print(char)

這段程式會逐一輸出字串 text 中的每個字元:

h
e
l
l
o

範例3:使用 range() 處理數字範圍

若想要處理一段數值範圍,可以使用 range() 函數:

for i in range(5):
    print(i)

這段程式會從 0 到 4 依序輸出:

0
1
2
3
4

range() 函數的用法

  • range(n):從 0 到 n-1
  • range(start, stop):從 startstop-1
  • range(start, stop, step):從 start 開始,每次增加 step,直到小於 stop
侍エンジニア塾

3. 善用 enumerate 函數

在使用 Python 處理序列時,有時會需要同時取得元素的索引與內容。這種情況下,可以使用 enumerate 函數,讓我們能更有效率地在迴圈中同時獲取索引和值。以下將介紹 enumerate 的基本用法與實用範例。

enumerate 函數的基本語法

使用 enumerate 時,每個元素都會自動附加一個索引,產生一個由索引與元素組成的配對(tuple)。語法如下:

for 索引, 元素 in enumerate(序列):
    處理
  • 索引:對應每個元素的位置編號。
  • 元素:序列中的各項資料。
  • 序列:可反覆處理的資料結構,例如串列、元組、字串等。

範例1:同時取得串列的索引與元素

以下範例展示如何透過 enumerate 同時取得索引與對應的水果名稱:

fruits = ["apple", "banana", "cherry"]
for index, fruit in enumerate(fruits):
    print(f"{index}: {fruit}")

輸出結果如下:

0: apple
1: banana
2: cherry

範例2:指定索引的起始值

enumerate 允許指定索引的起始值。預設是從 0 開始,也可以改為從 1 開始:

fruits = ["apple", "banana", "cherry"]
for index, fruit in enumerate(fruits, start=1):
    print(f"{index}: {fruit}")

輸出結果:

1: apple
2: banana
3: cherry

enumerate 函數的實用應用

顯示任務清單進度

enumerate 適合用於需要標號的項目,如任務追蹤列表:

tasks = ["洗衣服", "打掃", "做飯"]
for index, task in enumerate(tasks, start=1):
    print(f"任務{index}: {task} - 已完成")

輸出結果如下:

任務1: 洗衣服 - 已完成
任務2: 打掃 - 已完成
任務3: 做飯 - 已完成

根據索引條件進行處理

也可以利用索引來處理特定位置的資料:

numbers = [10, 20, 30, 40, 50]
for index, number in enumerate(numbers):
    if index % 2 == 0:
        print(f"{index} 號元素 {number} 是偶數索引")

輸出如下:

0 號元素 10 是偶數索引
2 號元素 30 是偶數索引
4 號元素 50 是偶數索引

小結

enumerate 函數在需要同時取得索引與值的情況下非常實用。可設定起始索引值,也能提升代碼可讀性,對於資料清單的追蹤與處理特別方便。

4. 使用 zip 函數進行多序列同步迴圈

Python 的 zip 函數可以同時對多個序列進行迴圈處理。這在需要同時對應處理兩個或多個列表時非常方便。以下將說明 zip 函數的基本用法與常見應用。

zip 函數的基本語法

zip 接受多個序列作為參數,並將每組對應元素打包成一個元組,然後返回一個可迴圈的物件。語法如下:

for 元素1, 元素2, ... in zip(序列1, 序列2, ...):
    處理
  • 元素1、元素2…:來自各序列的對應元素。
  • 序列1、序列2…:要同時處理的資料序列,例如串列或元組。

範例1:同時迴圈兩個串列

以下範例會同時處理姓名與分數:

names = ["Alice", "Bob", "Charlie"]
scores = [85, 92, 78]
for name, score in zip(names, scores):
    print(f"{name} 的分數是 {score}")

輸出如下:

Alice 的分數是 85
Bob 的分數是 92
Charlie 的分數是 78

範例2:同時處理三個以上的串列

zip 也可以處理三個以上的序列:

names = ["Alice", "Bob", "Charlie"]
scores = [85, 92, 78]
grades = ["B", "A", "C"]
for name, score, grade in zip(names, scores, grades):
    print(f"{name} 的分數是 {score},等級是 {grade}")

輸出如下:

Alice 的分數是 85,等級是 B
Bob 的分數是 92,等級是 A
Charlie 的分數是 78,等級是 C

zip 處理不同長度序列時的行為

當傳入的序列長度不一致時,zip 只會處理到最短序列為止:

names = ["Alice", "Bob"]
scores = [85, 92, 78]  # 有三個元素
for name, score in zip(names, scores):
    print(f"{name} 的分數是 {score}")

輸出如下,第三個分數會被忽略:

Alice 的分數是 85
Bob 的分數是 92

zip 的實用範例

成對顯示資料

以下範例將一個串列中的相鄰元素配對:

data = [10, 20, 30, 40]
for x, y in zip(data, data[1:]):
    print(f"配對: ({x}, {y})")

輸出如下:

配對: (10, 20)
配對: (20, 30)
配對: (30, 40)

小結

zip 是一個強大的工具,可用於同時處理多個序列,例如對應資料、合併列表、配對元素等。若要處理長度不一致的序列,也可以搭配 itertools.zip_longest 使用,實現更靈活的操作。

5. 列表生成式(List Comprehension)

Python 提供了一種強大且簡潔的技巧 ——「列表生成式」,可用來快速產生序列資料。使用列表生成式,可以讓原本需要使用 for 迴圈建立的列表變得更簡單、更易讀。這一章將透過基本語法與實際範例,說明列表生成式的便利性。

列表生成式的基本語法

基本語法如下:

[運算式 for 元素 in 序列]
  • 運算式:對每個元素執行的處理。
  • 元素:每次從序列中取出的一個值。
  • 序列:可反覆處理的資料結構,例如串列、元組、字串等。

範例1:基本的列表生成式

例如,將列表中每個數值乘以 2,可以用以下傳統方式:

numbers = [1, 2, 3, 4, 5]
doubled = []
for number in numbers:
    doubled.append(number * 2)
print(doubled)

使用列表生成式後,可簡化為:

numbers = [1, 2, 3, 4, 5]
doubled = [number * 2 for number in numbers]
print(doubled)

輸出結果:

[2, 4, 6, 8, 10]

條件式列表生成式

在列表生成式中也能加入條件式,篩選出特定元素再進行處理,語法如下:

範例2:加入條件的列表生成式

例如,只將偶數乘以 2,可這樣寫:

numbers = [1, 2, 3, 4, 5]
doubled_even = [number * 2 for number in numbers if number % 2 == 0]
print(doubled_even)

輸出結果:

[4, 8]

範例3:含有 else 的條件式生成

若想根據條件對不同元素執行不同處理,可使用 if 搭配 else

numbers = [1, 2, 3, 4, 5]
result = [number * 2 if number % 2 == 0 else number for number in numbers]
print(result)

這段程式會將偶數乘以 2,其他則保留原值:

[1, 4, 3, 8, 5]

小結

列表生成式讓我們可以以更簡潔的方式撰寫迴圈與資料處理邏輯,特別適合用於條件式處理與資料轉換。不過,當表達式過於複雜時,為了可讀性仍建議適時使用傳統 for 迴圈。

6. 字典的反覆處理

字典(dict)是 Python 中用來儲存鍵值對的主要資料結構之一。和列表或元組一樣,字典也可以進行迴圈處理,並根據需求取出鍵(key)、值(value)或兩者。本章將說明如何有效地迭代字典。

字典的基本迭代方式

在使用 for 迴圈處理字典時,可以選擇只取鍵、只取值,或同時取鍵與值。

範例1:只取得鍵(key)

直接對字典進行迴圈時,預設會取得所有鍵:

person = {"姓名": "太郎", "年齡": 30, "職業": "工程師"}
for key in person:
    print(key)

輸出結果:

姓名
年齡
職業

範例2:只取得值(value)

使用 values() 方法可以只遍歷字典中的值:

person = {"姓名": "太郎", "年齡": 30, "職業": "工程師"}
for value in person.values():
    print(value)

輸出結果:

太郎
30
工程師

範例3:同時取得鍵與值

使用 items() 方法,可以同時取得鍵與對應的值:

person = {"姓名": "太郎", "年齡": 30, "職業": "工程師"}
for key, value in person.items():
    print(f"{key}: {value}")

輸出結果:

姓名: 太郎
年齡: 30
職業: 工程師

條件式的字典處理

透過 if 條件語句,可篩選出符合條件的鍵值對:

範例4:只輸出符合條件的項目

以下範例僅輸出年齡 30 歲以上的成員:

people = {"太郎": 30, "花子": 25, "次郎": 35}
for name, age in people.items():
    if age >= 30:
        print(f"{name} 年齡在 30 歲以上")

輸出如下:

太郎 年齡在 30 歲以上
次郎 年齡在 30 歲以上

字典生成式(Dictionary Comprehension)

類似於列表生成式,也可以使用字典生成式來建立新的字典:

範例5:建立符合條件的新字典

以下程式碼會產生僅包含年齡 30 歲以上成員的新字典:

people = {"太郎": 30, "花子": 25, "次郎": 35}
adults = {name: age for name, age in people.items() if age >= 30}
print(adults)

輸出結果如下:

{'太郎': 30, '次郎': 35}

小結

Python 提供了多種方式來反覆處理字典,包括僅取鍵、值,或同時取得鍵值對。此外,也可以透過條件式與字典生成式來進行更靈活的資料操作。字典是非常實用的資料結構,善用這些技巧可以讓資料處理更高效。

7. 集合(set)的反覆處理

集合(set)是一種不允許重複元素的資料結構,常用於檢查特定值是否存在,或從列表中移除重複項目。與串列或元組不同的是,集合是無序的,無法使用索引來存取特定位置的元素,但可以透過 for 迴圈來遍歷集合中的所有元素。

本章將說明集合的基本反覆處理方式,以及如何根據條件進行篩選處理,並介紹集合特有的操作。

集合的基本迴圈處理

要遍歷集合中的所有元素,可以使用 for 迴圈。由於集合是無序的,因此每次輸出的順序可能會有所不同。

範例1:輸出集合中的所有元素

以下是遍歷集合並輸出所有元素的基本範例:

fruits = {"apple", "banana", "cherry"}
for fruit in fruits:
    print(fruit)

雖然輸出的順序不固定,但每個元素都只會出現一次:

banana
cherry
apple

條件式集合處理

也可以針對集合中的元素加入條件式進行篩選,透過 if 陳述式來處理符合條件的元素。

範例2:只輸出符合條件的元素

例如,只輸出長度大於等於 5 的水果名稱:

fruits = {"apple", "banana", "cherry", "fig", "kiwi"}
for fruit in fruits:
    if len(fruit) >= 5:
        print(fruit)

輸出結果如下:

banana
cherry
apple

集合推導式(Set Comprehension)

和列表、字典一樣,集合也可以使用推導式來建立新的集合,適合用於條件篩選或轉換資料。

範例3:根據條件建立新集合

以下範例會建立一個只包含長度大於等於 5 的水果名稱的新集合:

fruits = {"apple", "banana", "cherry", "fig", "kiwi"}
long_fruits = {fruit for fruit in fruits if len(fruit) >= 5}
print(long_fruits)

輸出如下(順序不固定):

{'banana', 'cherry', 'apple'}

小結

集合是一種不允許重複且無順序的資料結構,特別適合用於處理唯一資料或集合運算(如交集、差集等)。透過 for 迴圈與集合推導式,可以有效率地過濾與轉換資料。若善用其特性,集合在資料清理與比對上將會是非常實用的工具。

8. 善用 itertools 模組

itertools 是 Python 標準函式庫中的一個強大模組,專門用來輔助處理各種反覆操作。它提供了許多高效的函式,特別適合用來處理大量資料或進行進階的迴圈控制。本章將介紹 itertools 模組中常用的幾個函式,並說明實際應用方式。

itertools 模組的主要函式

itertools 提供了許多用於加強反覆處理能力的工具。以下是幾個代表性的函式及其使用方式。

1. count 函式

count 函式會從指定的數字開始,不斷遞增產生無限的數列。常用於產生不設上限的連續編號。

from itertools import count

for i in count(10):
    if i > 15:
        break
    print(i)

這段程式會從 10 開始輸出,直到 15 為止:

10
11
12
13
14
15

2. cycle 函式

cycle 函式會無限重複指定的序列,非常適合用來重複輸出某些模式。

from itertools import cycle

count = 0
for item in cycle(["A", "B", "C"]):
    if count == 6:
        break
    print(item)
    count += 1

這段程式會重複輸出 “A”、”B”、”C”,總共輸出 6 次:

A
B
C
A
B
C

3. repeat 函式

repeat 函式會重複某個指定的值。若指定次數,則會重複該次數;否則會無限重複。

from itertools import repeat

for item in repeat("Python", 3):
    print(item)

這段程式會將 “Python” 輸出三次:

Python
Python
Python

4. accumulate 函式

accumulate 函式會對序列中的元素進行累積運算,例如累加。也可以搭配自定義函式進行乘法、最大值等操作。

from itertools import accumulate

numbers = [1, 2, 3, 4, 5]
result = list(accumulate(numbers))
print(result)

這段程式會計算列表中數字的累加結果:

[1, 3, 6, 10, 15]

小結

itertools 模組提供了許多強大工具,能讓我們更靈活、有效率地處理反覆運算。特別是在需要大量資料處理、生成無限序列、或進行組合與排列等進階操作時,itertools 都能幫助我們簡化程式碼並提升效能。掌握這些工具,將能寫出更具專業水準的 Python 程式。

9. 總結

Python 提供了多種反覆處理的方式,每種方法都有其獨特的特點與適用情境。透過本系列內容,我們學習了如何使用各種工具來提升 Python 中的迴圈效率與可讀性。本章將回顧這些技巧,並提供選擇最適合方法的參考依據。

各種技巧的重點與用途

以下為每種反覆處理方法的簡要說明與應用情境:

1. for 迴圈

重點:Python 中最基本的反覆處理語法,簡單且通用性高。
用途:處理串列、元組、字串等序列資料。

2. enumerate 函數

重點:可同時取得索引與對應元素。
用途:當需要追蹤資料位置時,例如加上項目編號或判斷索引位置。

3. zip 函數

重點:可同時迭代多個序列。
用途:用於將多個資料對應起來進行處理,例如姓名與成績的配對。

4. 列表生成式

重點:可簡潔地建立新列表,支援條件判斷。
用途:對資料進行篩選、轉換、重組時的快速處理。

5. 字典的反覆處理

重點:可取得鍵、值,或同時取得鍵值配對。
用途:適用於資料鍵值結構的查詢、篩選、輸出等操作。

6. 集合的反覆處理

重點:集合內元素不重複、無順序。
用途:處理唯一值、移除重複、集合邏輯運算(交集、差集等)。

7. itertools 模組

重點:提供無限迴圈、組合、排列等進階功能。
用途:適合處理大量資料、需要高效率與進階邏輯的情境。

選擇最佳方法的建議

在進行反覆處理時,根據資料型態與處理目標選擇合適的方法相當重要。以下是根據不同需求的建議:

  1. 簡單處理串列或元組:使用基本的 for 迴圈即可。
  2. 需要索引:使用 enumerate 可以同時取得索引與資料。
  3. 同時處理多個序列:使用 zip 進行對應處理。
  4. 產生條件式新列表:使用列表生成式更簡潔高效。
  5. 需要操作字典或集合:善用 items()values() 或集合推導式。
  6. 需要進階處理或大量資料:使用 itertools 模組可提升效能與靈活性。

結語

Python 擁有豐富且強大的反覆處理工具,從基本的迴圈語法到進階模組皆一應俱全。透過靈活運用這些技巧,我們可以撰寫出更簡潔、高效、可讀性佳的程式碼。建議依照實際需求選擇最適合的方式,以提升開發效率與程式品質。

未來在開發過程中,請持續善用這些技巧,讓您的 Python 寫作更加靈活且強大!