4 迴圈與流程控制

迴圈與流程控制是撰寫程式相當重要的環節,它們可以幫助我們省去撰寫重複內容的程式並具備處理不同情境的程式分支。

4.1 迴圈

假設我們現在想做一件事情:我們想讓 Python 輸出美國影集六人行(Friends)的六個主要演員:

print "Jennifer Aniston"
print "Courteney Cox"
print "Lisa Kudrow"
print "Matt LeBlanc"
print "Matthew Perry"
print "David Schwimmer"

圖 4-1 輸出六個主要演員

或者我們可以先將這六位主要演員儲存在一個 list 中,稱為 starrings,再利用選擇 list 中元素的方式一一輸出:

starrings = ["Jennifer Aniston", "Courteney Cox", "Lisa Kudrow", "Matt LeBlanc", "Matthew Perry", "David Schwimmer"]
print starrings[0]
print starrings[1]
print starrings[2]
print starrings[3]
print starrings[4]
print starrings[5]

圖 4-2 輸出 list 中的六個元素

在不撰寫迴圈的情況下,我們還是能夠慢慢地複製貼上結構類似的程式,修改一些小地方,進而完成我們想要做的事情。但這確實不是一個好方法,試想如果我們要輸出的不再只有 6 個元素,而是 66、666 個這麼多元素呢?這時我們可以求助迴圈來協助!

4.1.1 for 迴圈

一個 for 迴圈結構如下:

for i in x:
    # 每次迭代執行的程式

Python 使用縮排(indent)來載明每次迭代要處理的事情,假如 x 是一個 list 或是 tuple,i 會由 x[0] 起始;當一次迭代結束,i 會更動為 x[1],以此類推;而在每一次迭代中,Python 都會執行縮排部分的程式。

starrings = ["Jennifer Aniston", "Courteney Cox", "Lisa Kudrow", "Matt LeBlanc", "Matthew Perry", "David Schwimmer"]

for starring in starrings:
    print starring

圖 4-3 for 迴圈

在這個 for 迴圈中,迭代子(iterator)我們取名作 starring,它是以文字的資料類型存在;我們也可以讓迭代子以整數的資料類型存在:

starrings = ["Jennifer Aniston", "Courteney Cox", "Lisa Kudrow", "Matt LeBlanc", "Matthew Perry", "David Schwimmer"]

for i in range(len(starrings)):
    print starrings[i]

圖 4-4 for 迴圈(2)

在這個迴圈中,迭代子(iterator)我們取名作 i,它是整數由 0 起始到 5 終止,我們藉助 range() 函數產生 0 到 5 的清單。

4.1.2 while 迴圈

一個 while 迴圈結構如下:

while 某些條件:
    # 每次迭代執行的程式

在每一次的迭代之前,Python 都會檢查某些條件是否成立,假如判斷結果為布林 True 就會執行每次迭代執行的程式;一但條件不成立,意即判斷結果為布林 False 迴圈就會終止。

我們試著寫輸出美國影集六人行(Friends)六個主要演員的 while 迴圈:

starrings = ["Jennifer Aniston", "Courteney Cox", "Lisa Kudrow", "Matt LeBlanc", "Matthew Perry", "David Schwimmer"]
i = 0

while i < 6:
    print starrings[i]
    i += 1

圖 4-5 while 迴圈

很重要的是 i += 1,假如忘記寫這一行程式,我們的 while 迴圈會無限次數地一直輸出 "Jennifer Aniston",原因是我們的判斷條件永遠成立(0 小於 6),所以會不斷地執行 print starrings[0]

4.1.3 兩種迴圈的運用時機

我們何時應該運用 for 迴圈、何時應該運用 while 迴圈呢?一個簡單的判斷是:假如我們明確知道程式的迭代次數,可以是個人偏好採用 for 迴圈或 while 迴圈;在不知道迭代次數的情形下,我們只能採用 while 迴圈。

這個說法還是略嫌抽象,舉一個例子說明會比較好理解。假如我們現在投擲一枚公正的銅板,想知道總共需要投擲幾次才會出現三個正面,這就是一個不知道迭代次數的問題。運氣好一點也許投擲三次,三次都是正面;運氣差一點的也許要投擲十幾次才湊得齊三次正面。讓我們寫一段簡單的程式來模擬這個例子:

import random

coin_flips = [] # 建立一個空的清單放置每一次投擲的結果
coin = ["Head", "Tail"]

while coin_flips.count("Head") < 3:
    coin_flips.append(coin[random.randint(0, 1)])

print coin_flips # 印出每次投擲的紀錄
print len(coin_flips) # 總共投擲了幾次

我們執行一次試試看:

圖 4-6 投擲硬幣

總共投擲了七次硬幣就投擲出了三次正面,每次投擲分別是反面、反面、正面、反面、正面、反面與正面。

我們再執行一次看看:

圖 4-7 投擲硬幣

這次投擲了四次硬幣就投擲出了三次正面,每次投擲分別是正面、正面、反面與正面。您可以試著自行執行幾次,看看每一輪投擲次數的差異。

4.1.4 迴圈與 dict

dict 的結構比 list 多了鍵值(key),如果沒有特別指定,迴圈輸出的會是 dict 的鍵值。

starrings = {
    "Rachel Green": "Jennifer Aniston",
    "Monica Geller": "Courteney Cox",
    "Phoebe Buffay": "Lisa Kudrow",
    "Joey Tribbiani": "Matt LeBlanc",
    "Chandler Bing": "Matthew Perry",
    "Ross Geller": "David Schwimmer"
}

for starring in starrings:
    print starring

圖 4-8 迴圈與 dict

比較清楚的寫法是在 dict 後面加入 .keys().values() 表示針對鍵值或內容進行迴圈的輸出。

starrings = {
    "Rachel Green": "Jennifer Aniston",
    "Monica Geller": "Courteney Cox",
    "Phoebe Buffay": "Lisa Kudrow",
    "Joey Tribbiani": "Matt LeBlanc",
    "Chandler Bing": "Matthew Perry",
    "Ross Geller": "David Schwimmer"
}

for starring in starrings.keys():
    print starring
print("---")
for starring in starrings.values():
    print starring

圖 4-9 迴圈與 dict(2)

4.1.5 更多的迴圈應用

如果希望同時將 dict 的鍵值與內容一起輸出,我們可以藉助 .items()

starrings = {
    "Rachel Green": "Jennifer Aniston",
    "Monica Geller": "Courteney Cox",
    "Phoebe Buffay": "Lisa Kudrow",
    "Joey Tribbiani": "Matt LeBlanc",
    "Chandler Bing": "Matthew Perry",
    "Ross Geller": "David Schwimmer"
}

for (key, value) in starrings.items():
    print "%s 由 %s 演出" % (key, value)

圖 4-10 更多的迴圈應用

我們可以讓迭代子再一次的迭代中代表多個值。

starrings = [
    ("Rachel Green", "Jennifer Aniston"),
    ("Monica Geller", "Courteney Cox"),
    ("Phoebe Buffay", "Lisa Kudrow"),
    ("Joey Tribbiani", "Matt LeBlanc"),
    ("Chandler Bing", "Matthew Perry"),
    ("Ross Geller", "David Schwimmer")
]

for (character, star) in starrings:
    print character + " 由 " + star + " 主演"

圖 4-11 更多的迴圈應用(2)

如果希望同時將 list 的索引值與元素輸出,可以使用 enumerate() 函數。

starrings = ["Jennifer Aniston", "Courteney Cox", "Lisa Kudrow", "Matt LeBlanc", "Matthew Perry", "David Schwimmer"]

for (index, starring) in enumerate(starrings):
    print "%i: %s" % (index, starring)

圖 4-12 更多的迴圈應用(3)

假如我想同時針對兩個清單應用迴圈,可以使用 zip() 函數。

characters = ["Rachel Green", "Monica Geller", "Phoebe Buffay", "Joey Tribbiani", "Chandler Bing", "Ross Geller"]
starrings = ["Jennifer Aniston", "Courteney Cox", "Lisa Kudrow", "Matt LeBlanc", "Matthew Perry", "David Schwimmer"]

for (character, star) in zip(characters, starrings):
    print character + " 由 " + star + " 主演"

圖 4-13 更多的迴圈應用(4)

4.2 流程控制

流程控制可以幫助我們在程式中撰寫不同的劇本(scenario),根據不同的判斷條件執行不同的程式。我們使用 ifelifelse 建立出不同的分支,它的外觀架構長得像這樣子:

if 條件一:
    # 程式一
elif 條件二:
    # 程式二
else:
    # 程式三

如果條件一的判斷結果為 True 就執行程式一,條件二的判斷結果為 True 就執行程式二;假如條件一與條件二的判斷結果皆為 False,就執行程式三。如果有更多的條件,只要增加 elif 的描述即可。

4.2.1 兩個分支

舉例來說,一個喜愛運動的人早上起床會看天氣決定當天的運動行程,在兩種天氣條件下,使用 ifelse 就可以建立出兩個分支的運動行程:

import random

weathers = ["晴天", "下雨"]
weather = weathers[random.randint(0, 1)]

if weather == "晴天":
    print "天氣是%s,去戶外跑步" % weather
else:
    print "天氣是%s,去健身房" % weather

圖 4-14 兩個分支

圖 4-15 兩個分支(2)

4.2.2 三個分支

在三種天氣條件下,使用 ifelifelse 就可以建立出三個分支的運動行程:

import random

weathers = ["晴天", "下雨", "暴風雨"]
weather = weathers[random.randint(0, 2)]

if weather == "晴天":
    print "天氣是%s,去戶外跑步" % weather
elif weather == "下雨":
    print "天氣是%s,去健身房" % weather
else:
    print "天氣是%s,睡回籠覺" % weather

圖 4-16 三個分支

圖 4-17 三個分支(2)

圖 4-18 三個分支(3)

4.3 結合迴圈與流程控制

4.3.1 break

在迴圈執行的過程中,滿足某條件時候就離開迴圈,舉例來說,將 list starrings 中的元素一一輸出時,假如碰到 "Matt LeBlanc" 就離開迴圈,這樣我們可以輸出所有的女性演員:

starrings = ["Jennifer Aniston", "Courteney Cox", "Lisa Kudrow", "Matt LeBlanc", "Matthew Perry", "David Schwimmer"]

for starring in starrings:
    if starring == "Matt LeBlanc":
        break
    print starring

圖 4-19 break

4.3.2 continue

在迴圈執行的過程中,滿足某條件時候略過那一次迭代,舉例來說,將 list starrings 中的元素一一輸出時,假如碰到 "Matt LeBlanc" 就略過不輸出,這樣我們可以輸出沒有繼續演衍生劇 Joey 的另外五位演員:

starrings = ["Jennifer Aniston", "Courteney Cox", "Lisa Kudrow", "Matt LeBlanc", "Matthew Perry", "David Schwimmer"]

for starring in starrings:
    if starring == "Matt LeBlanc":
        continue
    print starring

圖 4-20 continue

練習題

  • 我們有一個公正的骰子,想知道總共需要投擲幾次才會出現三個六,請寫一段簡單的程式來模擬投擲骰子的過程,最後記得將每一次投擲的結果以及投擲的總次數輸出(請參考章節中的投擲硬幣範例)

  • 分別將 1 到 100 印出,但是碰到 3 的倍數的時候改為輸出 "三的倍數",碰到 5 的倍數的時候改為輸出 "五的倍數",如果同時是 3 跟 5 的公倍數,則輸出 "十五的倍數"

results matching ""

    No results matching ""