2.13. 迴圈控制¶
有兩個關鍵字可以改變迴圈的執行方式:
break-- 立即離開迴圈。continue-- 略過本次迭代剩餘的部分,直接開始下一次迭代。
兩者都只作用於它們所在的最內層迴圈。
2.13.1. break¶
使用 break 可在條件成立時立即停止迴圈。這是典型的「搜尋並停止」模式:
found = None
for item in items:
if matches(item):
found = item
break
if found is not None:
print("found:", found)
在 while True: 迴圈中,break 是讓迴圈結束的方式:
while True:
line = next_line()
if line == "quit":
break
process(line)
2.13.2. continue¶
使用 continue 可略過迴圈主體剩餘的部分,直接跳到下一次迭代。它很適合在迴圈內篩選項目:
for n in numbers:
if n < 0:
continue # skip negatives
print(n)
同樣的效果也可以用一個 if 區塊包住主體剩餘的部分來寫。當略過的條件比保留的條件更容易事先描述清楚時,continue 有時會更清楚。
在迴圈內,continue 扮演的角色就像函式中提早 return 一樣:略過你不處理的情況,讓主要工作維持在外層縮排的扁平結構。篩選並處理的迴圈是其典型形式:
for item in items:
if item is None:
continue
if not item.is_valid():
continue
process(item)
縮排的 process(item) 那一行才是實際的工作;上方的每個守衛條件都明確指出哪些項目會被略過。
2.13.3. 迴圈上的 else¶
for 與 while 都接受一個選用的 else 區塊。當迴圈未遇到 break 而正常結束時,它就會執行。最常見的用途是搜尋迴圈在找不到任何結果時想要有個後備處理:
for item in items:
if matches(item):
print("found:", item)
break
else:
print("no match")
如果觸發了 break,else 區塊就會被略過。可以把這個結構讀成「for X in Y: ...;否則,如果我們從未跳出,就執行 Z」。
2.13.4. 常見的迴圈模式¶
在實際的指令碼中,有幾種模式經常出現:
輪詢(Polling) -- 在繼續往下之前,等待某個條件變為真。主體使用
pass,這是 Python 的無操作陳述式;每個縮排區塊都必須至少包含一條陳述式,而pass就是用來表達「這裡什麼都不做」:while not ready(): pass proceed()
狀態機(State machine) -- 一個
while True:迴圈,根據狀態變數來決定要做什麼。當工作能清楚拆分成幾個具名階段時很有用:state = "header" for line in lines: if state == "header": if line.startswith("---"): state = "body" elif state == "body": print(line)
累積(Accumulating) -- 在走訪一個序列的同時逐步建立結果:
total = 0 for x in samples: total += x mean = total / len(samples)
許多累積迴圈都有使用內建函式的單行等價寫法。只要適用,就優先採用內建函式:
sum()-- 將可迭代物件中的每個項目相加。any()-- 只要至少有一個項目為真值就回傳True。all()-- 只有當每個項目都為真值時才回傳True。sorted()-- 一個依序排列項目的新清單。len()-- 項目的數量(前提是該可迭代物件知道自己的長度)。
>>> samples = [3, 1, 4, 1, 5, 9, 2, 6] >>> sum(samples) 31 >>> sum(samples) / len(samples) # mean 3.875 >>> max(samples) 9 >>> min(samples) 1 >>> sorted(samples) [1, 1, 2, 3, 4, 5, 6, 9] >>> any([False, False, True]) True >>> all([True, True, False]) False
內建版本比起手動撰寫相同的迴圈更簡短、更清楚,而且通常更快。