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」,並且結束迴圈。

我們可以用這張圖很快地瞭解上面這個迴圈:

Python for 迴圈運作原理 | 程式設計


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() 函數究竟是什麼東西呢?其實嚴格來說,range() 並不能算是一個函數,而是一個類別,但因為我們還沒有認真討論過物件導向,我們就姑且說它是一個函數吧!

如果真的很想知道 range() 函數的資料型態,那麼我們可以使用之前講過的type 函數來檢查它的資料型態:

>>> 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


breakcontinue 非常的相似,但是有一個極為龐大的不同點。讓我們把剛剛 6 的倍數的那個例子拿到這邊,並且將 continue 變成 break,看看發生甚麼事情吧:

for i in range(1, 21): 
    if i % 6 == 0: 
        break 
    print(i, end=", ")

下面是執行的結果:

1, 2, 3, 4, 5, 

這樣我們就知道差別在哪裡了吧!breakcontinue 最主要的差別在於,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() 便執行了。


馬上練習!
完成 10 個練習題,
並且獲取學習點數!
開始練習
上一章節
下一章節
使用者分享的影片來自 YouTube。瞭解更多
+1 
感謝內容貢獻者 此篇文章由 1 位使用者共同編輯而成,並且由學呀的編輯團隊負責維護。點此查看編輯者名單。