再論Python迴圈 — While Loop
前文曾經提及,while迴圈會在條件為True的狀況下,重複執行內部的程式區塊內容。這裡要再進一步的說明while迴圈。用白話文來說,就是『在某種條件下的特定期間內』的意思。例如:在旅遊的期間、在上班的期間、在疫情的期間等等。
看看下面while迴圈的例子:
首先第一行我們指定變數x的值為0,這是一個起始數字。
在第二行,當x小於五的狀態下,在螢幕顯示結果(第三行)後,並且將變數x的值加1。(第四行)。最後當迴圈執行完畢後,在螢幕顯示變數x最後的值(第五行)。
x = 0while x < 5: print("第 {} 次執行 while 迴圈:".format(str(x+1))) x= x + 1print("總共執行 while 迴圈共:{} 次".format(str(x)))
執行結果為五次:
在函式中的迴圈
我們可以把while迴圈寫在一個函式裡面:
def attempts(num): x = 1 while x <= num: print("第一次 " + str(x)) x += 1 print("執行完畢")
透過attempts(數字)來呼叫,例如我們放入10。
attempts(10)
倒數計時迴圈
設計一個count_down函式,函式裡面使用while迴圈倒數計時。只要輸入欲開始倒數的數字,程式就會自動從開始數字倒數計算到零為止。
def count_down(start): curr = start while (curr > 0): print("倒數",curr) curr -= 1 print("0,時間到!")count_down(10)
從上面三個例子可以發現,當我們使用迴圈之前,必須注意起始變數(例如 x=0)是否已經正確設定。
我們一般在剛開始寫while迴圈時,常常會忘記設定起始變數,結果就會導致NameError。解決這個問題,就是要在迴圈開始前設定起始變數。像前面的例子一樣 x = 0、x = 1或者是curr = start都是設定起始變數的方法。
另外一個常見的錯誤是設定了錯誤的起始變數。例如下面的例子:
x =1sum = 0while x < 10: sum += x x += 1
product = 1while x < 10: product = product * x x += 1
print(sum, product)
在這個例子裡面,結果是45與1。為什麼第二個數字是1?
因為第一組迴圈執行到最後,x 已經為10。當到了要執行第二組迴圈時,由於 x 已經為10 ,導致迴圈沒有啟動執行,product即維持原來的數字1。
像這樣的錯誤我們很難找到,因為Python本身不會顯示錯誤訊息。若要解決這個問題,我們需要重新將 x 設定為1,才可以正確的執行第二組迴圈。
因此只要迴圈的條件為True,主體程式就會反覆執行,當條件為False時,while迴圈會終止。如果條件一開始就是False的話,主體程式就完全不會執行。如果起始變數在程式的開始與中間都會被使用的話,在中間的時候必須注意起始變數的值是否已經被改變了。
無限迴圈
看下面的式子:
while x % 2 == 0: x = x /2
如果這這裡的x為0,會發生什麼情形?
上面的程式碼執行的結果會出現像never ending story 般的無限循環迴圈。無限的迴圈可能會讓你的電腦因資源的耗盡而當掉。要修正這個問題,我們可以加上一行判斷,來對 x 值進行判斷。
if x !=0: while x % 2 == 0: x = x /2
上面的if statement 可以確保只有在x值不是0的狀況下,才會執行迴圈。
我們再看一個例子:
我們希望這個程式可以產生一組從開始到結束數字的迴圈。如果你執行下面的程式碼,應該會得到一個無限迴圈。
def print_range(start, end): n = start while n <= end: print(n)print_range(1, 5)
要怎麼修改才不會發生無限迴圈?
def print_range(start, end): n = start while n <= end: print(n) n += 1print_range(1, 5)
答案是在while迴圈裡面加上 n += 1。在每次迴圈執行完畢的時候,讓n的數字比目前大1,這樣子就不會出現無限迴圈的現象了。
用break來阻斷無限迴圈
無限迴圈也不是完全不可以使用。如果你希望迴圈在某個情況下停止,但是又不確定那個情況會在什麼時候發生,這時候可以使用無限迴圈加上一個break陳述來實現這個功能。
換句話說,在迴圈中加入break,也是避免while迴圈變成無限循環的方式之一。
while True: do_something() if requested_to_stop() break
例如下面的程式碼:程式碼會一直不斷的執行直到使用者輸入q才會跳出迴圈。
While True: action = input("請填寫一個句子或鍵入q 結束對話") if action =="q": break print(action)
文字對話介面
這個方式很適合用來設計操作對話的介面。下面是對話介面的簡單示範:
def display_menu():
print('OO會員管理系統')
print('-'*40)
print('1. 輸入會員資料')
print('2. 輸入購買事件')
print('3. 輸入退貨事件')
print('4. 輸入換貨事件')
print('5. 顯示會員購買明細')
print('0. 結束程式')
print('-'*40)# 主程式
def main():
while True:
display_menu()
user_choice = input('請輸入選項: ')
if user_choice == '1':
print('您選擇的是:輸入會員資料')
elif user_choice == '2':
print('您選擇的是:輸入購買事件')
elif user_choice == '3':
print('您選擇的是:輸入退貨事件')
elif user_choice == '4':
print('您選擇的是:輸入換貨事件')
elif user_choice == '5':
print('您選擇的是:顯示會員購買明細')
else:
break
#主程式####
if __name__ == "__main__":
main()
猜數字遊戲
也可以用來製作簡單的遊戲。下面是一個簡單的猜數字遊戲。使用者可以透過對話方式,輸入1到10的數字來猜。這裡的設計是要強制使用者猜數字,直到猜對為止我們使用while迴圈。如果你希望使用者只能猜某個特定次數的話(例如猜5次),可以改用for迴圈來實現。
import random random_number = random.randint(1,10)while True:
user_guess = input("請從 1 到 10 中間選一個數字 ")
user_guess = int(user_guess) if user_guess < random_number:
print("你猜的數字太小了")
elif user_guess > random_number:
print("你猜的數字太大了")
else:
print("恭喜,猜對了")
play_again = input("要不要再試一次? (y/n) ") if play_again =="y":
random_number = random.randint(1,10)
user_guess = None
else:
print("結束遊戲,歡迎下次再來")
break
在製作猜數字遊戲時,必須先匯入random套件,這個套件可以隨機產生數字。我們在這裡使用randint方法從1到10中間隨機產生一個數字( random.randint(1,10) )。
接者就是比較使用者輸入的數字( user_guess )與隨機產生的數字(random_number)之間的大小。比較前,記得先將使用者輸入的字串轉換為數字( user_guess = int(user_guess) )。使用while迴圈,當條件為True時,不斷的循環直到猜到並且選擇 n 結束遊戲為止,在結束遊戲的地方我們使用break來跳出迴圈。
總結來說,迴圈可以用在很多地方,在使用上也需要注意無限迴圈的情形。程式會產生預期以外的無限迴圈,大都是迴圈執行條件沒有隨著迴圈的執行而發生變化。在撰寫程式的時候要特別注意。