2.12. 迴圈

迴圈會重複執行同一段程式碼。Python 有兩種形式:while 只要條件持續為真就會一直執行,而 for 則會走訪序列中的各個項目。

並排的流程圖。while:測試條件,若為真則執行 主體,然後重複。for:從可迭代物件取出下一個項目, 執行主體,重複直到取盡。

while 會不斷測試一個條件;for 則走訪一個序列直到取盡為止。

2.12.1. while 迴圈

while 迴圈會在每次迭代前測試其條件,並持續執行主體直到測試結果變為假:

count = 0
while count < 5:
    print(count)
    count += 1

輸出:

0
1
2
3
4

如果條件在一開始為真且永遠不會變為假,迴圈就會永遠執行下去。while True: 是主迴圈的標準慣用寫法,並以 break 明確地退出:

while True:
    step()
    if done():
        break

2.12.2. for 迴圈

for 迴圈會走訪一個可迭代物件的各個項目 -- 清單、tuple、字串、bytes、dict,或任何其他支援迭代的物件:

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

輸出:

apple
banana
cherry

同樣的形式也適用於字串,此時每個項目都是長度為一的字串:

for letter in "OpenMV":
    print(letter)

輸出:

O
p
e
n
M
V

直接迭代一個 dict 會依插入順序產生它的鍵:

for key in {"a": 1, "b": 2}:
    print(key)

輸出:

a
b

每一輪都會把迴圈變數(fruitletterkey)繫結到下一個項目。迴圈結束後,該變數仍保留最後一次迭代時的值。

2.12.3. range

若要對一個數值範圍進行迴圈,請使用 range()

  • range(stop) -- 0、1、...、stop - 1。

  • range(start, stop) -- start、start + 1、...、stop - 1。

  • range(start, stop, step) -- 帶有自訂步長(負值則向下計數)。

for i in range(5):           # 0, 1, 2, 3, 4
    print(i)

for i in range(2, 8, 2):     # 2, 4, 6
    print(i)

for i in range(10, 0, -1):   # 10, 9, ..., 1
    print(i)

range() 會惰性地產生數值 -- 它不會在記憶體中建立清單。若要取得實際的 list,請將其包裹起來:list(range(10))

2.12.4. enumerate

當迴圈同時需要索引與項目時,enumerate() 會產生 (index, item) 配對:

for i, name in enumerate(["a", "b", "c"]):
    print(i, name)
# 0 a
# 1 b
# 2 c

傳入第二個引數即可讓索引從零以外的值開始:enumerate(items, start=1)

2.12.5. zip

若要同步走訪兩個(或更多)可迭代物件,請使用 zip()。它會在每個位置產生一個 tuple,並在最短的輸入耗盡時停止:

names  = ["alice", "bob", "carol"]
scores = [88, 92, 70]

for name, score in zip(names, scores):
    print(name, score)

輸出:

alice 88
bob 92
carol 70

2.12.6. 使用 := 的內嵌指派

海象運算子 := 是一種既是指派又是運算式的寫法。它會繫結一個名稱,並在同一時間求值為相同的值。在 while 迴圈中,這能把常見的「讀取、檢查、主體」模式收合成一行:

# without walrus
value = next_value()
while value is not None:
    process(value)
    value = next_value()

# with walrus
while (value := next_value()) is not None:
    process(value)

這兩種形式做的事情相同。當指派的重複確實損害了可讀性時,才使用 :=;不要只為了賣弄聰明而使用它。在大多數位置上,括號是必要的,以維持運算式的明確性。