機
器
人
for 迴圈
迴圈這個東西,在程式中可說是不可或缺的—假設你要重複一件事情 100 次,你應該不會想要重複寫一段程式 100 次,而是希望電腦能夠自動重複程式 100 次。上個章節中,我們建立了對於迴圈的概念,在這個章節,讓我們來探索 Python 中的 for 迴圈吧!
列表 list
Python 的 for 迴圈與其他程式語言有些許的不同,不同的點在於,在 Python 中,for 迴圈必須有一個能夠作為基準的列表(list)才能運作。
在這裡,讓我們來建立一個列表叫做 fruits:
fruits = ["apple", "banana", "cherry"]
現在,我們想要把 fruits 列表中的每一項水果都印出來,要怎麼做呢?讓我們回想一下列表這個東西,我們可以一個個將水果印出來,像是這樣:
print(fruits[0])
print(fruits[1])
print(fruits[2])
如此一來,螢幕上便會出現「apple」、「banana」、「cherry」三種水果的字串。但是如果今天這個列表有一百萬種水果呢?我們會不會需要複製 print()
一百萬次呢?
以我們目前對於 Python 的瞭解,我們的確需要複製貼上一百萬次 print()
函數,但是很顯然的,一定有方法可以讓這項工作簡單一點。那麼,這個神奇的方法是什麼呢?那就是 for 迴圈。
for 迴圈
讓我們先看看使用 for 迴圈時,印出這些水果的字串要麼做:
for fruit in fruits:
print(fruit)
什麼?就這麼簡單?沒錯!這樣看起來,for 迴圈的確很方便,但是似乎有些艱澀難懂。但如果我們把 fruits 變數的列表代進去看,就會好懂很多了:
for fruit in ["apple", "banana", "cherry"]:
print(fruit)
簡單來說,電腦在看到第一行的 for fruit ... :
迴圈時,就會知道要開始進行迴圈的工作了。此時,電腦會好奇:
這個迴圈要重複幾次呢?
接著電腦就會想到:
列表中有三個東西,因此總共要執行三次。
於是電腦就開始執行迴圈了。執行第一次時,電腦會建立一個變數,叫做 fruit,並且將 fruit 的值設為「apple」,因此在第二行的 print(fruit)
時,會印出「apple」。接下來,在執行第二次時,fruit 變成了「banana」,因此在 print
時印出「banana」。同樣的邏輯,在第三次時電腦印出「cherry」,並且結束迴圈。
我們可以用這張圖很快地瞭解上面這個迴圈:
range() 函數
現在,我們知道了要如何讓迴圈執行與列表長度相對應的次數,但是你有沒有想過一個問題:如果今天我們沒有列表,迴圈不就不能執行了嗎?遇到這樣的問題,我們要如何解決呢?很簡單,如果沒有列表,那就製作一個吧!
但是,假設今天我們要讓迴圈重複一百萬次,我們總不可能徒手打出一個一百萬個項目的列表吧!這種時候,range()
函數就發揮功用了。如果今天我們要印出 0 ~ 5 總共 6 個數字:
>>> for i in [0, 1, 2, 3, 4, 5]:
... print(i, end=", ")
...
0, 1, 2, 3, 4, 5,
>>> for i in range(6):
... print(i, end=", ")
...
0, 1, 2, 3, 4, 5,
上述兩段程式所輸出的結果都一樣,差別只在於程式的部分。我們希望讓迴圈重複 6 次,因此在第一個例子中,我們直接列出了一個含有 0 ~ 5 共 6 個數字的列表。然而同樣的問題又回來了,如果我們要讓迴圈重複一百萬次,那我們可是會打字打到手斷掉的!
在第二段程式中,我們並沒有直接打出列表,而是使用了 range()
函數。在函數的括號中,我們輸入了「6」這個值。我們可以得到一個結論:range(6)
和 [0, 1, 2, 3, 4, 5]
在 for 迴圈中運行的效果是一樣的。
於是我們知道,range(x)
將會生成一個含有 0 開始,總共 x 個數字的整數列表。舉例來說,剛剛的 range(6)
便生成了一個含有從 0 開始,總共 6 個數字的列表。
但是這裡要注意了:range()
函數所回傳的並不是一個真正的列表,只是在 for 迴圈中,range()
函數跟列表的運作模式基本上是一模一樣的。接著,讓我們看看range()
函數還有什麼厲害的功能吧!
range(x, y)
將會回傳一個從 x 到 y,但是不包含 y 的整數數列:
>>> for i in range(3, 7):
... print(i, end=", ")
...
3, 4, 5, 6,
range(x, y, z)
將會回傳一個從 x 到 y,不包含 y,且公差為 z 的數列:
>>> for i in range(4, 16, 4):
... print(i, end=", ")
...
4, 8, 12,
既然 range()
函數回傳的不是一個數列,那麼 range()
函數究竟是什麼東西呢?
>>> type(range(6))
<class 'range'>
但是,如果你真的很想把這個 range 的奇怪東西變成一個列表呢?那應該要怎麼做?其實,我們強大的 Python 早已經幫我們想好解決辦法了!只要使用list()
就可以了:
>>> a = list(range(6))
>>> print(a)
[0, 1, 2, 3, 4, 5]
>>> type(a)
<class 'list'>
continue
今天有一個列表叫做 c,其所帶有的值是從 0 到 9 的 10 個數字:
c = list(range(10))
而現在,如果我們想要將列表中的每一個數字全部都印出來,我們便可以使用 for 迴圈,像是這樣:
for i in c:
print(i, end=", ")
於是我們將會得到這樣的結果:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
但是假設我們今天就是特別討厭 4 這個數字,因此想要在每次迴圈要印出 4 之前就跳過 4,直接到下一個數,這樣要怎麼做呢?讓我們看看以下的解決方法:
for i in c:
if i == 4:
continue
print(i, end=", ")
這樣的程式將會產出以下的結果:
0, 1, 2, 3, 5, 6, 7, 8, 9
我們可以看到的是,電腦的確沒有印出 4 這個數字。所以究竟這程式是如何辦到的?在第二行程式中,我們放置了一個 if i == 4:
的判斷式;在第三行程式中,則有一個 continue
。
Continue 就字面上,有「繼續」的意思。在一個迴圈中 continue
就好像在告訴電腦:
這圈迴圈先結束吧!我們直接繼續下一圈。
因此範例中的這段程式,可以被解讀為:
用 i 這個變數對 c 列表做迴圈:
如果 i 是 4:
跳過這次迴圈,直接到下個數
印出(i, 結尾用「, 」)
讓我們再來看看下一個例子。現在我們想要印出 1 ~ 20 中,非 6 的倍數的所有數字,並且將數字間用逗號隔開,那麼我們可以這樣做:
for i in range(1, 21):
if i % 6 == 0:
continue
print(i, end=", ")
第二、三行中,if i % 6 == 0
,判斷了變數 i 是否為 6 的倍數,如果是,則 continue
,也就是跳過該數,因此我們得到以下的輸出結果:
1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 19, 20,
break
break
和 continue
非常的相似,但是有一個極為龐大的不同點。讓我們把剛剛 6 的倍數的那個例子拿到這邊,並且將 continue
變成 break
,看看發生甚麼事情吧:
for i in range(1, 21):
if i % 6 == 0:
break
print(i, end=", ")
下面是執行的結果:
1, 2, 3, 4, 5,
這樣我們就知道差別在哪裡了吧!break
和 continue
最主要的差別在於,continue
將這次的迴圈跳過,而 break
直接將整個迴圈停止運作。
讓我們看看下一個例子,已知有一個數列 o,其數字會不停地向上增加,我們的目標是印出所有小於 30 的數字,並且將數字之間用逗號隔開。這裡是我們的數列 o:
o = [-3, 2, 3, 7, 15, 16, 19, 22, 28, 33, 37, 41, 42]
利用 for 迴圈以及 break
關鍵字,我們可以寫出這樣的程式:
for i in o:
if i >= 30:
break
print(i, end=", ")
執行後,我們將能得到這樣的結果:
-3, 2, 3, 7, 15, 16, 19, 22, 28,
for-else
跟 if-else 結構 很像,for 迴圈也可以加上一個 else 得到一個 for-else 的程式結構。else 後的程式會在列表中的項目執行完後執行,讓我們看看以下的例子:
for name in ["Bob", "Amy", "Dan"]:
print(name)
else:
print("名字印完了。")
這段程式將會產生以下的結果:
Bob
Amy
Dan
名字印完了。
else 中的程式,只有在列表中的項目被自然地用盡時才會執行,如果今天是因為 break
而跳出迴圈,則 else 中的程式將不會被執行。
運用這個特色,我們就可以做出一寫很有趣的程式,像是下面這個範例:
names = ["Bob", "Amy", "Dan"]
searchName= input("你要查什麼名字呢?")
for name in names:
if searchName == name:
print(name, "找到了!")
break
else:
print("找不到這個名字!")
讓我們執行兩次程式,並且輸入不同的名字:
>>> 你要查什麼名字呢?Amy
Amy 找到了!
>>> 你要查什麼名字呢?Sean
找不到這個名字!
第一次執行時,因為 Amy 這個名字存在於 names 列表中,因此在第二次迴圈時,第五行的 if searchName == name:
被觸發了,電腦因而 break
了迴圈。記得剛才說 else 中的城市不會在 break
後執行嗎?因為這裡 break
了迴圈,因此最後一行的 print()
沒有被執行。
第二次執行時,因為 Sean 這個名字不在 names
列表中,因此第五行的判斷式並沒有被觸發。一直到列表的項目用盡了,迴圈還沒有被 break
掉,因此 else 中的 print()
便執行了。