主題: 學習筆記

Python 電腦科學與程式設計導論 第三講:迭代

MIT OpenCourseWare 6.100L 第三講筆記:while、for、range、流程控制、近似法與迭代模式。

迭代(iteration)很像把你的意圖塞進一台節拍器:只要條件成立,或只要還有下一個元素,就繼續敲。MIT 6.100L Lecture 3 用幾個非常「人類」的例子,把 whilefor 的直覺釘進腦內:迷失森林、Netflix 追劇、階乘、running sum。這篇文章把它們整理成可操作的心智模型,再加上一點「工程師的防呆習慣」。

學迴圈的最短路徑

不要背語法。先問一句:「我到底是在等一個條件變化?」 還是 「我是在走訪一個序列?」

前者幾乎都用 while;後者幾乎都用 for


1) while:條件為王,但也最容易召喚黑洞

while 的語意很純粹:

只要條件為 True,就執行區塊;每次執行完再回去檢查一次。

所以它非常適合「你不知道要重複幾次」的任務:等待使用者輸入正確格式、等待某個狀態改變、等待資料到齊……(也因此最容易寫出「永遠等不到明天」的無窮迴圈)。

迷失森林的 Python 版本(含大小寫防呆)

where = input("Go left or right? ")

# 先把輸入轉小寫,避免 RIGHT / Right 造成語意偏差
where = where.strip().lower()

while where == "right":
    where = input("Go left or right? ").strip().lower()

print("You got out of the Lost Forest!")

注意:無窮迴圈的兩種死法(都很常見)

  • 條件永遠不會變:你在迴圈裡沒有更新跟條件相關的變數。
  • 條件其實會變,但你沒察覺:例如大小寫、空白、型別(字串 vs 數字)讓條件判斷偏掉。

2) Netflix 的「Are you still watching?」其實是一個 while 思想實驗

Lecture 3 用 Netflix 追劇當比喻:只要還有下一集、只要你還在互動,它就繼續播放;如果你睡著或播完了,條件變成 False,迴圈停止,然後丟出提示。

你可以把它想成:

  • 狀態:still_has_episodeuser_is_active
  • 迴圈:只要兩者都成立,就 play_next_episode()

這個例子重要的不是 Netflix,而是你會開始用「狀態 + 條件」思考流程控制。


3) for:優雅地走訪序列(尤其是 range

當你想做的事其實是「做 N 次」或「走過一段整數範圍」,for 幾乎總是更乾淨:

# while 版本(你要自己維護 n)
n = 0
while n < 5:
    print(n)
    n += 1

# for 版本(把「n 會怎麼變」交給 range)
for n in range(5):
    print(n)

range(start, stop, step):stop 不包含在內,這是設計不是陷阱

你會在很多地方受益:

  • 對齊索引:range(len(arr)) 產生合法索引
  • 避免多印一個:stop 不包含 → 邊界更一致
  • 倒著走:range(4, 0, -1) 這種倒數很直覺

筆記:最容易記的規則

range(5) 會產生 [0,1,2,3,4]。不是 Python 在耍你,是它在幫你:這樣剛好對齊「序列長度為 5 的合法索引」。


4) Running Sum:把「累積」變成一種迴圈肌肉記憶

Running sum(累積總和)是最值得早早練熟的模式之一:你會在統計、資料處理、演算法裡反覆遇到它。

mysum = 0
for i in range(10):   # i: 0..9
    mysum += i
print(mysum)          # 45

小訣竅:腦內配音法(超有效)

每次迭代都用一句話描述狀態: 「現在 i 是多少?mysum 目前是多少?這一輪會加上什麼?」 這其實就是把 Python Tutor 的視覺化搬到你的腦袋裡。


5) 階乘(factorial):while vs for 的可讀性對決

階乘是經典案例:n! = 1 × 2 × ... × n

# while 版本:你要手動推進 i
x = 4
i = 1
factorial = 1
while i <= x:
    factorial *= i
    i += 1
print(f"{x} factorial is {factorial}")
# for 版本:少了「推進 i」的維護成本
x = 4
factorial = 1
for i in range(1, x + 1):
    factorial *= i
print(f"{x} factorial is {factorial}")

筆記:工程視角的結論(務實)

只要你是在走訪一個明確序列(例如 1..n),for 通常更不易出錯; while 的強項是「等狀態變化」或「次數未知」。


6) 迴圈控制:breakcontinue、以及那個看起來像在偷懶的 pass

三個關鍵字,三種不同的「流程手勢」:

  • break:直接離開迴圈(緊急出口)
  • continue:跳過本輪,直接去下一輪(略過不想處理的情況)
  • pass:什麼都不做(語法占位用)

範例:輸入驗證(含 while-else)

correct_password = "magic123"
attempts = 0

while attempts < 3:
    pwd = input("請輸入密碼: ")
    if pwd == correct_password:
        print("歡迎登入!")
        break
    else:
        print("密碼錯誤,再試一次。")
        attempts += 1
else:
    # 只有「沒有被 break 打斷」才會跑到這裡
    print("多次輸入錯誤,帳號鎖定!")

小訣竅:while-else 其實很優雅

它把「正常跑完」與「中途 break」分流得很乾淨: break = 你提前離席else = 你把流程走到自然結束

範例:用 continue 篩選資料(少一層巢狀 if)

numbers = [4, -2, 0, 7, -5, 3]
positives = []

for n in numbers:
    if n <= 0:
        continue
    positives.append(n)

print("正數有:", positives)  # [4, 7, 3]

7) Debug 迴圈的三條鐵律(讓你少掉一半痛苦)

  1. 先寫出「迴圈不變量」:每輪開始時,你希望哪些條件成立?(例如 mysum 永遠等於已處理元素的總和)
  2. 檢查邊界(off-by-one):你到底要包含 end 嗎?range 的 stop 不包含在內,這點要非常清楚。
  3. 需要可視化時,直接上工具:用 Python Tutor 看每一步變數怎麼變,對初學者是降維打擊。

延伸閱讀(精準補強)