天天看點

【Python3.7學習筆記】六、控制語句和循環學習筆記目錄

【Python3.7學習筆記】六、控制語句和循環

學習筆記目錄

【Python3.7學習筆記】一、環境搭建

【Python3.7學習筆記】二、第一個python程式

【Python3.7學習筆記】三、變量和簡單資料類型

【Python3.7學習筆記】四、清單

【Python3.7學習筆記】五、字典

【Python3.7學習筆記】六、控制語句和循環

目錄

文章目錄

  • 學習筆記目錄
    • 目錄
    • 簡單示例
    • 條件測試
      • 檢查相等
      • 檢查相等忽略大小寫
      • 檢查是否不相等
      • 比較數字
      • 檢查多個條件
        • 使用and
        • 使用or
      • 檢查特定值是否包含在清單中
      • 檢查特定值是否不包含在清單中
    • if語句
      • 簡單的if語句
      • if-else語句
      • if-elif-else語句
      • 多個elif語句
      • 省略else語句
      • 測試多個條件
    • 使用if語句處理清單
      • 檢查特殊元素
      • 确定清單不是空的
      • 使用多個清單
      • 設定if語句格式
    • 使用者輸入
      • input()函數原理
      • 編寫清晰的程式
      • 使用int()擷取數值輸入
      • 求模運算符
    • while循環
      • 使用while循環
      • 讓使用者選擇何時退出
      • 使用标志
      • 使用break退出循環
      • 在循環中使用continue
      • 避免無限循環
    • 使用while循環來處理清單和字典
      • 在清單之間移動元素
      • 删除包含特定值得所有清單元素
      • 使用使用者輸入來填充字典

簡單示例

簡單的示例,看看if是如何工作的,如果目前汽車名是bmw,則以全部大寫方式列印輸出,如:

cars = ['audi', 'bmw', 'subaru', 'toyota']

for car in cars:
    if car == 'bmw':
        print(car.upper())
    else:
        print(car.title())
           

輸出結果:

audi
BMW
subaru
toyota
           

條件測試

每條if語句的核心都是一個值為True或False的表達式,這種表達式稱為條件測試

python根據條件測試的值來決定是否執行if語句中得代碼。如果條件測試的值為True,則執行if語句後面的代碼;否則python會忽略這些代碼。

檢查相等

将一個變量的目前值與特定值進行比較,如:

car = 'bmw'
print(car == 'bmw')
car = 'audi'
print(car == 'bmw')
           

輸出結果:

True
False
           

檢查相等忽略大小寫

可以判斷時忽略大小寫,如:

car = 'Audi'
print(car.lower()=='audi')
car = 'bmw'
print(car.upper()=='BMW')
           

輸出結果:

True
True
           

檢查是否不相等

car = 'bmw'

if car != "audi":
    print("Is not audi!")
           

輸出結果:

Is not audi!
           

比較數字

age = 18
print(age == 18)
print(age < 20)
print(age <= 20)
print(age > 20)
print(age >= 20)
           

輸出結果:

True
True
True
False
False
           

檢查多個條件

使用and

要檢查是否兩個條件都為True,可使用and連接配接,如果2個條件都為True,則表達式為True;如果至少有一個測試沒有通過,表達式為False,如:

age_0 = 20
age_1 = 18

print(age_0 >= 21 and age_1 >= 21)
age_0 = 21
age_1 = 22
print(age_0 >= 21 and age_1 >= 21)
           

輸出結果:

False
True
           

使用or

至少滿足一個條件,表達式為True,如果都不滿足條件,則為False,如:

age_0 = 20
age_1 = 18

print(age_0 >= 21 or age_1 >= 21)
age_0 = 21
age_1 = 22
print(age_0 >= 21 or age_1 >= 21)
           

輸出結果:

False
True
           

檢查特定值是否包含在清單中

關鍵字in可用于判斷特定值是否包含在清單中。如:

motocycles = ['honda', 'yamaha', 'suzuki', 'ducati']

print('yamaha' in motocycles)
           

輸出結果:

檢查特定值是否不包含在清單中

關鍵字not in,可以用于判斷特定值是否不包含在清單中,如:

motocycles = ['honda', 'yamaha', 'suzuki', 'ducati']

print('yamaha' not in motocycles)
print('yamaha1' not in motocycles)
           

輸出結果:

False
True
           

if語句

簡單的if語句

簡單的if語句格式,如下:

if condition_test:
	do something
           

示例:

age = 19
	if age >= 18:
		print("You are old enough to vote!")
           

如果條件測試的結果為True ,Python就會執行緊跟在if 語句後面的代碼;否則 Python将忽略這些代碼。

輸出結果:

You are old enough to vote!
           

在if 語句中,縮進的作用與for 循環中相同。如果測試通過了,将執行if 語句後面所有縮進的代碼行,否則将忽略它們。

在緊跟在if 語句後面的代碼塊中,可根據需要包含任意數量的代碼行

示例:

age = 19
if age >= 18:
	print("You are old enough to vote!") 
	print("Have you registered to vote yet?")
           

輸出結果:

You are old enough to vote!
Have you registered to vote yet?
           

如果age 的值小于18,這個程式将不會有任何輸出。

if-else語句

經常需要在條件測試通過了時執行一個操作,并在沒有通過時執行另一個操作;在這種情況下,可使用Python提供的if-else 語句。if-else 語句塊類似于簡單的if 語句,但 其中的else 語句讓你能夠指定條件測試未通過時要執行的操作。

示例:

age = 17
if age >= 18:
	print("You are old enough to vote!")
	print("Have you registered to vote yet?") 
else:
	print("Sorry, you are too young to vote.")
	print("Please register to vote as soon as you turn 18!")
           

如果if的條件測試通過了,就執行第一個縮進的print 語句塊;如果測試結果為False ,就執行else 代碼塊。這次age 小于18,條件測試未通過,是以執行else 代 碼塊中的代碼:

輸出結果:

Sorry, you are too young to vote.
Please register to vote as soon as you turn 18!
           

上述代碼之是以可行,是因為隻存在兩種情形:要麼夠投票的年齡,要麼不夠。if-else 結構非常适合用于要讓Python執行兩種操作之一的情形。在這種簡單的if-else 結構 中,總是會執行兩個操作中的一個。

if-elif-else語句

經常需要檢查超過兩個的情形,為此可使用Python提供的if-elif-else 結構。Python隻執行if-elif-else 結構中的一個代碼塊,它依次檢查每個條件測試,直到遇到通過

了的條件測試。測試通過後,Python将執行緊跟在它後面的代碼,并跳過餘下的測試。 在現實世界中,很多情況下需要考慮的情形都超過兩個。例如,來看一個根據年齡段收費的遊樂場:

  • 4歲以下免費;
  • 4~18歲收費5美元;
  • 18歲(含)以上收費10美元。

如果隻使用一條if 語句,如何确定門票價格呢?下面的代碼确定一個人所屬的年齡段,并列印一條包含門票價格的消息:

age = 12
❶ if age<4:
		print("Your admission cost is $0.")
❷ elif age < 18:
		print("Your admission cost is $5.")
❸ else:
		print("Your admission cost is $10.")
           

❶處的if 測試檢查一個人是否不滿4歲,如果是這樣,Python就列印一條合适的消息,并跳過餘下的測試。❷處的elif 代碼行其實是另一個if 測試,它僅在前面的測試未通過 時才會運作。在這裡,我們知道這個人不小于4歲,因為第一個測試未通過。如果這個人未滿18歲,Python将列印相應的消息,并跳過else 代碼塊。如果if 測試和elif 測試都 未通過,Python将運作❸處else 代碼塊中的代碼。

在這個示例中,❶處測試的結果為False ,是以不執行其代碼塊。然而,第二個測試的結果為True (12小于18),是以将執行其代碼塊。輸出為一個句子,向使用者指出了門票 價格:

隻要年齡超過17歲,前兩個測試就都不能通過。在這種情況下,将執行else 代碼塊,指出門票價格為10美元。 為讓代碼更簡潔,可不在if-elif-else 代碼塊中列印門票價格,而隻在其中設定門票價格,并在它後面添加一條簡單的print 語句:

age = 12
❶ if age<4:
		price = 0
❷ elif age < 18:
		price = 5
❸ else:
		price = 10
❹ print("Your admission cost is $" + str(price) + ".")	
           

❶處、❷處和❸處的代碼行像前一個示例那樣,根據人的年齡設定變量price 的值。在if-elif-else 結構中設定price 的值後,一條未縮進的print 語句❹會根據這個變 量的值列印一條消息,指出門票的價格。

這些代碼的輸出與前一個示例相同,但if-elif-else 結構的作用更小,它隻确定門票價格,而不是在确定門票價格的同時列印一條消息。除效率更高外,這些修訂後的代碼 還更容易修改:要調整輸出消息的内容,隻需修改一條而不是三條print 語句。

多個elif語句

可根據需要使用任意數量的elif 代碼塊,例如,假設前述遊樂場要給老年人打折,可再添加一個條件測試,判斷顧客是否符合打折條件。下面假設對于65歲(含)以上的老

人,可以半價(即5美元)購買門票:

age = 12
	if age < 4: 
		price = 0
	elif age < 18: 
		price = 5
❶ elif age < 65: 
		price = 10
❷ else:
		price = 5
print("Your admission cost is $" + str(price) + ".")
           

這些代碼大都未變。第二個elif 代碼塊(見❶)通過檢查确定年齡不到65歲後,才将門票價格設定為全票價格——10美元。請注意,在else 代碼塊(見❷)中,必須将所賦的 值改為5,因為僅當年齡超過65(含)時,才會執行這個代碼塊。

省略else語句

Python并不要求if-elif 結構後面必須有else 代碼塊。在有些情況下,else 代碼塊很有用;而在其他一些情況下,使用一條elif 語句來處理特定的情形更清晰:

age = 12
if age < 4: 
	price = 0
elif age < 18: 
	price = 5
elif age < 65: 
	price = 10
❶ elif age >= 65: 
	price = 5
print("Your admission cost is $" + str(price) + ".")
           

❶處的elif 代碼塊在顧客的年齡超過65(含)時,将價格設定為5美元,這比使用else 代碼塊更清晰些。經過這樣的修改後,每個代碼塊都僅在通過了相應的測試時才會執 行。

else 是一條包羅萬象的語句,隻要不滿足任何if 或elif 中的條件測試,其中的代碼就會執行,這可能會引入無效甚至惡意的資料。如果知道最終要測試的條件,應考慮使用 一個elif 代碼塊來代替else 代碼塊。這樣,你就可以肯定,僅當滿足相應的條件時,你的代碼才會執行。

測試多個條件

if-elif-else 結構功能強大,但僅适合用于隻有一個條件滿足的情況:遇到通過了的測試後,Python就跳過餘下的測試。這種行為很好,效率很高,讓你能夠測試一個特定的

條件。

然而,有時候必須檢查你關心的所有條件。在這種情況下,應使用一系列不包含elif 和else 代碼塊的簡單if 語句。在可能有多個條件為True ,且你需要在每個條件為True 時都采取相應措施時,适合使用這種方法。

下面再來看前面的比薩店示例。如果顧客點了兩種配料,就需要確定在其比薩中包含這些配料:

❶ requested_toppings = ['mushrooms', 'extra cheese']
❷ if 'mushrooms' in requested_toppings: 
		print("Adding mushrooms.")
❸ if 'pepperoni' in requested_toppings: 
		print("Adding pepperoni.")
❹ if 'extra cheese' in requested_toppings: 
		print("Adding extra cheese.")
print("\nFinished making your pizza!")
           

我們首先建立了一個清單,其中包含顧客點的配料(見❶)。❷處的if 語句檢查顧客是否點了配料蘑菇(‘mushrooms’ ),如果點了,就列印一條确認消息。❸處檢查配料辣 香腸(‘pepperoni’ )的代碼也是一個簡單的if 語句,而不是elif 或else 語句;是以不管前一個測試是否通過,都将進行這個測試。❹處的代碼檢查顧客是否要求多加芝 士(‘extra cheese’);不管前兩個測試的結果如何,都會執行這些代碼。每當這個程式運作時,都會進行這三個獨立的測試。

在這個示例中,會檢查每個條件,是以将在比薩中添加蘑菇并多加芝士:

Adding mushrooms. 
Adding extra cheese.
Finished making your pizza!
           

如果像下面這樣轉而使用if-elif-else 結構,代碼将不能正确地運作,因為有一個測試通過後,就會跳過餘下的測試:

requested_toppings = ['mushrooms', 'extra cheese']
if 'mushrooms' in requested_toppings: 
	print("Adding mushrooms.")
elif 'pepperoni' in requested_toppings: 
	print("Adding pepperoni.")
elif 'extra cheese' in requested_toppings: 
	print("Adding extra cheese.")
print("\nFinished making your pizza!")
           

第一個測試檢查清單中是否包含’mushrooms’ ,它通過了,是以将在比薩中添加蘑菇。然而,Python将跳過if-elif-else 結構中餘下的測試,不再檢查清單中是否包 含’extra cheese’和’pepperoni’。其結果是,将添加顧客點的第一種配料,但不會添加其他的配料:

Adding mushrooms.
Finished making your pizza!
           

總之,如果你隻想執行一個代碼塊,就使用if-elif-else 結構;如果要運作多個代碼塊,就使用一系列獨立的if 語句。

使用if語句處理清單

通過結合使用if 語句和清單,可完成一些有趣的任務:對清單中特定的值做特殊處理;高效地管理不斷變化的情形,如餐館是否還有特定的食材;證明代碼在各種情形下都将按

預期那樣運作。

檢查特殊元素

本章開頭通過一個簡單示例示範了如何處理特殊值’bmw’ ——它需要采用不同的格式進行列印。既然你對條件測試和if 語句有了大緻的認識,下面來進一步研究如何檢查清單 中的特殊值,并對其做合适的處理。

繼續使用前面的比薩店示例。這家比薩店在制作比薩時,每添加一種配料都列印一條消息。通過建立一個清單,在其中包含顧客點的配料,并使用一個循環來指出添加到比薩中 的配料,可以以極高的效率編寫這樣的代碼:

requested_toppings = ['mushrooms', 'green peppers', 'extra cheese']
for requested_topping in requested_toppings:
	print("Adding " + requested_topping + ".")
print("\nFinished making your pizza!")
           

輸出很簡單,因為上述代碼不過是一個簡單的for 循環:

Adding mushrooms. 
Adding green peppers. 
Adding extra cheese.
Finished making your pizza!
           

然而,如果比薩店的青椒用完了,該如何處理呢?為妥善地處理這種情況,可在for 循環中包含一條if 語句:

requested_toppings = ['mushrooms', 'green peppers', 'extra cheese']
for requested_topping in requested_toppings: 
	if requested_topping == 'green peppers':
		print("Sorry, we are out of green peppers right now.") 
	else:
		print("Adding " + requested_topping + ".") 
print("\nFinished making your pizza!")
           

輸出結果:

Adding mushrooms.
Sorry, we are out of green peppers right now.
Adding extra cheese.
Finished making your pizza!
           

确定清單不是空的

到目前為止,對于處理的每個清單都做了一個簡單的假設,即假設它們都至少包含一個元素。我們馬上就要讓使用者來提供存儲在清單中的資訊,是以不能再假設循環運作時清單

不是空的。有鑒于此,在運作for 循環前确定清單是否為空很重要。 下面在制作比薩前檢查顧客點的配料清單是否為空。如果清單是空的,就向顧客确認他是否要點普通比薩;如果清單不為空,就像前面的示例那樣制作比薩:

❶ requested_toppings = []
❷ if requested_toppings:
		for requested_topping in requested_toppings:
			print("Adding " + requested_topping + ".") 
		print("\nFinished making your pizza!")
❸ else:
		print("Are you sure you want a plain pizza?")
           

在這裡,我們首先建立了一個空清單,其中不包含任何配料(見❶)。在❷處我們進行了簡單檢查,而不是直接執行for 循環。在if 語句中将清單名用在條件表達式中 時,Python将在清單至少包含一個元素時傳回True ,并在清單為空時傳回False 。如果requested_toppings 不為空,就運作與前一個示例相同的for 循環;否則,就列印 一條消息,詢問顧客是否确實要點不加任何配料的普通比薩(見❸)。

在這裡,這個清單為空,是以輸出如下——詢問顧客是否确實要點普通比薩:

Are you sure you want a plain pizza?
           

如果這個清單不為空,将顯示在比薩中添加的各種配料的輸出。

使用多個清單

顧客的要求往往五花八門,在比薩配料方面尤其如此。如果顧客要在比薩中添加炸薯條,該怎麼辦呢?可使用清單和if 語句來确定能否滿足顧客的要求。 來看看在制作比薩前如何拒絕怪異的配料要求。下面的示例定義了兩個清單,其中第一個清單包含比薩店供應的配料,而第二個清單包含顧客點的配料。這次對

于requested_toppings 中的每個元素,都檢查它是否是比薩店供應的配料,再決定是否在比薩中添加它:

available_toppings = ['mushrooms', 'olives', 'green peppers', 'pepperoni', 'pineapple', 'extra cheese']
requested_toppings = ['mushrooms', 'french fries', 'extra cheese']

for requested_topping in requested_toppings:
	if requested_topping in available_toppings:
		print("Adding " + requested_topping + ".") 
	else:
		print("Sorry, we don't have " + requested_topping + ".") print("\nFinished making your pizza!")
           

我們定義了一個清單,其中包含比薩店供應的配料。請注意,如果比薩店供應的配料是固定的,也可使用一個元組來存儲它們。在❷處,我們又建立了一個清單,其中 包含顧客點的配料,請注意那個不同尋常的配料——‘french fries’。在❸處,我們周遊顧客點的配料清單。在這個循環中,對于顧客點的每種配料,我們都檢查它是否包 含在供應的配料清單中(見❹);如果答案是肯定的,就将其加入到比薩中,否則将運作else 代碼塊(見❺):列印一條消息,告訴顧客不供應這種配料。

這些代碼的輸出整潔而詳實:

Adding mushrooms.
Sorry, we don't have french fries. 
Adding extra cheese.
Finished making your pizza!
           

設定if語句格式

本章的每個示例都展示了良好的格式設定習慣。在條件測試的格式設定方面,PEP 8提供的唯一建議是,在諸如== 、>= 和<= 等比較運算符兩邊各添加一個空格,例如,if

age < 4:要比if age<4:好。 這樣的空格不會影響Python對代碼的解讀,而隻是讓代碼閱讀起來更容易。

使用者輸入

input()函數原理

函數input() 讓程式暫停運作,等待使用者輸入一些文本。擷取使用者輸入後,Python将其存儲在一個變量中,以友善你使用。 例如,下面的程式讓使用者輸入一些文本,再将這些文本呈現給使用者:

message = input("Tell me something, and I will repeat it back to you: ") 
print(message)
           

函數input() 接受一個參數:即要向使用者顯示的提示 或說明,讓使用者知道該如何做。在這個示例中,Python運作第1行代碼時,使用者将看到提示Tell me something, and I will repeat it back to you:。程式等待使用者輸入,并在使用者按Enter鍵後繼續運作。輸入存儲在變量message中,接下來的print(message)将輸入呈現給用 戶:

Tell me something, and I will repeat it back to you: Hello everyone! 
Hello everyone!
           

編寫清晰的程式

每當你使用函數input() 時,都應指定清晰而易于明白的提示,準确地指出你希望使用者提供什麼樣的資訊——指出使用者該輸入任何資訊的提示都行,如下所示:

name = input("Please enter your name: ") 
print("Hello, " + name + "!")
           

通過在提示末尾(這裡是冒号後面)包含一個空格,可将提示與使用者輸入分開,讓使用者清楚地知道其輸入始于何處,如下所示:

Please enter your name: Eric 
Hello, Eric!
           

有時候,提示可能超過一行,例如,你可能需要指出擷取特定輸入的原因。在這種情況下,可将提示存儲在一個變量中,再将該變量傳遞給函數input() 。這樣,即便提示超過 一行,input() 語句也非常清晰。

prompt = "If you tell us who you are, we can personalize the messages you see." 
prompt += "\nWhat is your first name? "
name = input(prompt) 
print("\nHello, " + name + "!")
           

這個示例示範了一種建立多行字元串的方式。第1行将消息的前半部分存儲在變量prompt 中;在第2行中,運算符+= 在存儲在prompt 中的字元串末尾附加一個字元串。 最終的提示橫跨兩行,并在問号後面包含一個空格,這也是出于清晰考慮:

If you tell us who you are, we can personalize the messages you see. 
What is your first name? Eric
Hello, Eric!
           

使用int()擷取數值輸入

使用函數input() 時,Python将使用者輸入解讀為字元串。請看下面讓使用者輸入其年齡的解釋器會話:

>>> age = input("How old are you? ") 
How old are you? 21
>>> age
'21'
           

使用者輸入的是數字21,但我們請求Python提供變量age 的值時,它傳回的是’21’ ——使用者輸入的數值的字元串表示。我們怎麼知道Python将輸入解讀成了字元串呢?因為這個數 字用引号括起了。如果我們隻想列印輸入,這一點問題都沒有;但如果你試圖将輸入作為數字使用,就會引發錯誤:

>>> age = input("How old are you? ")
How old are you? 21
 ❶ >>> age >= 18
Traceback (most recent call last): 
	File "<stdin>", line 1, in <module>
❷ TypeError: unorderable types: str() >= int()
           

你試圖将輸入用于數值比較時(見❶),Python會引發錯誤,因為它無法将字元串和整數進行比較:不能将存儲在age 中的字元串’21’ 與數值18 進行比較(見❷)。 為解決這個問題,可使用函數int() ,它讓Python将輸入視為數值。函數int() 将數字的字元串表示轉換為數值表示,如下所示:

>>> age = input("How old are you? ")
How old are you? 21 
❶ >>> age = int(age)
>>> age >= 18 
True
           

在這個示例中,我們在提示時輸入21 後,Python将這個數字解讀為字元串,但随後int() 将這個字元串轉換成了數值表示(見❶)。這樣Python就能運作條件測試了:将變 量age (它現在包含數值21)同18 進行比較,看它是否大于或等于18。測試結果為True 。

如何在實際程式中使用函數int() 呢?請看下面的程式,它判斷一個人是否滿足坐過山車的身高要求:

height = input("How tall are you, in inches? ") 
height = int(height)

if height >= 36:
	print("\nYou're tall enough to ride!")
else:
	print("\nYou'll be able to ride when you're a little older.")
           

在這個程式中,為何可以将height同36進行比較呢?因為在比較前,height = int(height)将輸入轉換成了數值表示。如果輸入的數字大于或等于36,我們就告訴使用者 他滿足身高條件:

How tall are you, in inches? 71 
You're tall enough to ride!
           

将數值輸入用于計算和比較前,務必将其轉換為數值表示。

求模運算符

處理數值資訊時,求模運算符 (%)是一個很有用的工具,它将兩個數相除并傳回餘數:

>>> 4 % 3 
1
>>> 5 % 3
2
>>> 6 % 3
0
>>> 7 % 3 
1
           

求模運算符不會指出一個數是另一個數的多少倍,而隻指出餘數是多少。 如果一個數可被另一個數整除,餘數就為0,是以求模運算符将傳回0。你可利用這一點來判斷一個數是奇數還是偶數:

number = input("Enter a number, and I'll tell you if it's even or odd: ") number = int(number)

if number % 2 == 0:
	print("\nThe number " + str(number) + " is even.")
else:
	print("\nThe number " + str(number) + " is odd.")
           

偶數都能被2整除,是以對一個數(number)和2執行求模運算的結果為零,即number % 2 == 0,那麼這個數就是偶數;否則就是奇數。

Enter a number, and I'll tell you if it's even or odd: 42 
The number 42 is even.
           

while循環

for 循環用于針對集合中的每個元素都一個代碼塊,而while 循環不斷地運作,直到指定的條件不滿足為止。

使用while循環

你可以使用while 循環來數數,例如,下面的while 循環從1數到5:

current_number = 1
while current_number <= 5:
	print(current_number) current_number += 1
           

在第1行,我們将current_number 設定為1,進而指定從1開始數。接下來的while 循環被設定成這樣:隻要current_number 小于或等于5,就接着運作這個循環。循環中 的代碼列印current_number的值,再使用代碼current_number += 1(代碼current_number = current_number + 1的簡寫)将其值加1。

隻要滿足條件current_number <= 5,Python就接着運作這個循環。由于1小于5,是以Python列印1,并将current_number加1,使其為2;由于2小于5,是以Python打 印2 ,并将current_number 加1 ,使其為3 ,以此類推。一旦current_number 大于5,循環将停止,整個程式也将到此結束:

1 
2 
3 
4
5
           

你每天使用的程式很可能就包含while 循環。例如,遊戲使用while 循環,確定在玩家想玩時不斷運作,并在玩家想退出時停止運作。如果程式在使用者沒有讓它停止時停止運 行,或者在使用者要退出時還繼續運作,那就太沒有意思了;有鑒于此,while 循環很有用。

讓使用者選擇何時退出

可使用while 循環讓程式在使用者願意時不斷地運作,如下面的程式parrot.py所示。我們在其中定義了一個退出值,隻要使用者輸入的不是這個值,程式就接着運作:

❶ prompt = "\nTell me something, and I will repeat it back to you:" 
prompt += "\nEnter 'quit' to end the program. "
❷ message = ""
❸ while message != 'quit':
		message = input(prompt) 
		print(message)
           

在❶處,我們定義了一條提示消息,告訴使用者他有兩個選擇:要麼輸入一條消息,要麼輸入退出值(這裡為’quit’ )。接下來,我們建立了一個變量——message (見❷), 用于存儲使用者輸入的值。我們将變量message 的初始值設定為空字元串"" ,讓Python首次執行while 代碼行時有可供檢查的東西。Python首次執行while 語句時,需要 将message 的值與’quit’ 進行比較,但此時使用者還沒有輸入。如果沒有可供比較的東西,Python将無法繼續運作程式。為解決這個問題,我們必須給變量message 指定一個 初始值。雖然這個初始值隻是一個空字元串,但符合要求,讓Python能夠執行while 循環所需的比較。隻要message 的值不是’quit’ ,這個循環(見❸)就會不斷運作。

首次遇到這個循環時,message是一個空字元串,是以Python進入這個循環。執行到代碼行message = input(prompt)時,Python顯示提示消息,并等待使用者輸入。不管用 戶輸入是什麼,都将存儲到變量message 中并列印出來;接下來,Python重新檢查while 語句中的條件。隻要使用者輸入的不是單詞’quit’ ,Python就會再次顯示提示消息并等 待使用者輸入。等到使用者終于輸入’quit’ 後,Python停止執行while 循環,而整個程式也到此結束:

Tell me something, and I will repeat it back to you: 
Enter 'quit' to end the program. Hello everyone! 
Hello everyone!

Tell me something, and I will repeat it back to you: 
Enter 'quit' to end the program. Hello again.
Hello again.

Tell me something, and I will repeat it back to you: 
Enter 'quit' to end the program. quit
quit
           

這個程式很好,唯一美中不足的是,它将單詞’quit’ 也作為一條消息列印了出來。為修複這種問題,隻需使用一個簡單的if 測試:

prompt = "\nTell me something, and I will repeat it back to you:" 
prompt += "\nEnter 'quit' to end the program. "
message = ""
while message != 'quit':
	message = input(prompt)
	if message != 'quit': 
		print(message)
           

現在,程式在顯示消息前将做簡單的檢查,僅在消息不是退出值時才列印它:

Tell me something, and I will repeat it back to you: 
Enter 'quit' to end the program. Hello everyone! 
Hello everyone!

Tell me something, and I will repeat it back to you: 
Enter 'quit' to end the program. Hello again.
Hello again.

Tell me something, and I will repeat it back to you: 
Enter 'quit' to end the program. quit
           

使用标志

在前一個示例中,我們讓程式在滿足指定條件時就執行特定的任務。但在更複雜的程式中,很多不同的事件都會導緻程式停止運作;在這種情況下,該怎麼辦呢?

例如,在遊戲中,多種事件都可能導緻遊戲結束,如玩家一艘飛船都沒有了或要保護的城市都被摧毀了。導緻程式結束的事件有很多時,如果在一條while 語句中檢查所有這些 條件,将既複雜又困難。

在要求很多條件都滿足才繼續運作的程式中,可定義一個變量,用于判斷整個程式是否處于活動狀态。這個變量被稱為标志 ,充當了程式的交通信号燈。你可讓程式在标志 為True 時繼續運作,并在任何事件導緻标志的值為False 時讓程式停止運作。這樣,在while 語句中就隻需檢查一個條件——标志的目前值是否為True ,并将所有測試(是 否發生了應将标志設定為False 的事件)都放在其他地方,進而讓程式變得更為整潔。

下面來在前一節的程式parrot.py中添加一個标志。我們把這個标志命名為active (可給它指定任何名稱),它将用于判斷程式是否應繼續運作:

prompt = "\nTell me something, and I will repeat it back to you:" 
prompt += "\nEnter 'quit' to end the program. "
❶ active = True 
❷ while active:
		message = input(prompt)
		❸ if message == 'quit': 
				active = False
		❹ else: 
				print(message)
           

我們将變量active 設定成了True (見❶),讓程式最初處于活動狀态。這樣做簡化了while 語句,因為不需要在其中做任何比較——相關的邏輯由程式的其他部分處理。隻 要變量active 為True ,循環就将繼續運作(見❷)。

在while 循環中,我們在使用者輸入後使用一條if 語句來檢查變量message 的值。如果使用者輸入的是’quit’ (見❸),我們就将變量active 設定為False ,這将導 緻while 循環不再繼續執行。如果使用者輸入的不是’quit’ (見❹),我們就将輸入作為一條消息列印出來。

這個程式的輸出與前一個示例相同。在前一個示例中,我們将條件測試直接放在了while 語句中,而在這個程式中,我們使用了一個标志來指出程式是否處于活動狀态,這樣如 果要添加測試(如elif 語句)以檢查是否發生了其他導緻active 變為False 的事件,将很容易。在複雜的程式中,如很多事件都會導緻程式停止運作的遊戲中,标志很有 用:在其中的任何一個事件導緻活動标志變成False 時,主遊戲循環将退出,此時可顯示一條遊戲結束消息,并讓使用者選擇是否要重新玩。

使用break退出循環

要立即退出while 循環,不再運作循環中餘下的代碼,也不管條件測試的結果如何,可使用break 語句。break 語句用于控制程式流程,可使用它來控制哪些代碼行将執行,

哪些代碼行不執行,進而讓程式按你的要求執行你要執行的代碼。 例如,來看一個讓使用者指出他到過哪些地方的程式。在這個程式中,我們可以在使用者輸入’quit’ 後使用break 語句立即退出while 循環:

prompt = "\nPlease enter the name of a city you have visited:" 
prompt += "\n(Enter 'quit' when you are finished.) "
❶ while True:
		city = input(prompt)
		if city == 'quit': 
			break
		else:
			print("I'd love to go to " + city.title() + "!")
           

以while True打頭的循環(見❶)将不斷運作,直到遇到break語句。這個程式中的循環不斷輸入使用者到過的城市的名字,直到他輸入’quit’為止。使用者輸入’quit’ 後,将執行break 語句,導緻Python退出循環:

Please enter the name of a city you have visited:
(Enter 'quit' when you are finished.) New York 
I'd love to go to New York!

Please enter the name of a city you have visited: 
(Enter 'quit' when you are finished.) San Francisco 
I'd love to go to San Francisco!

Please enter the name of a city you have visited: 
(Enter 'quit' when you are finished.) quit
           

注意 在任何Python循環中都可使用break 語句。例如,可使用break 語句來退出周遊清單或字典的for 循環。

在循環中使用continue

要傳回到循環開頭,并根據條件測試結果決定是否繼續執行循環,可使用continue 語句,它不像break 語句那樣不再執行餘下的代碼并退出整個循環。例如,來看一個從1數 到10,但隻列印其中偶數的循環:

❶
current_number = 0
while current_number < 10:
	current_number += 1
	if current_number % 2 == 0:
		continue 
	print(current_number)
           

我們首先将current_number 設定成了0,由于它小于10,Python進入while 循環。進入循環後,我們以步長1的方式往上數(見❶),是以current_number 為1。接下 來,if 語句檢查current_number 與2的求模運算結果。如果結果為0(意味着current_number 可被2整除),就執行continue 語句,讓Python忽略餘下的代碼,并傳回 到循環的開頭。如果目前的數字不能被2整除,就執行循環中餘下的代碼,Python将這個數字列印出來:

1 
3 
5 
7 
9
           

避免無限循環

每個while 循環都必須有停止運作的途徑,這樣才不會沒完沒了地執行下去。例如,下面的循環從1數到5:

x=1
while x <= 5:
	print(x) 
	x += 1
           

但如果你像下面這樣不小心遺漏了代碼行x += 1,這個循環将沒完沒了地運作:

# 這個循環将沒完沒了地運作! 
x=1
while x <= 5:
	print(x)
           

在這裡,x的初始值為1,但根本不會變,是以條件測試x <= 5始終為True,導緻while循環沒完沒了地列印1,如下所示:

1
1
1
1 
--snip--
           

每個程式員都會偶爾因不小心而編寫出無限循環,在循環的退出條件比較微妙時尤其如此。如果程式陷入無限循環,可按Ctrl + C,也可關閉顯示程式輸出的終端視窗。 要避免編寫無限循環,務必對每個while 循環進行測試,確定它按預期那樣結束。如果你希望程式在使用者輸入特定值時結束,可運作程式并輸入這樣的值;如果在這種情況下程

序沒有結束,請檢查程式處理這個值的方式,确認程式至少有一個這樣的地方能讓循環條件為False 或讓break 語句得以執行。

使用while循環來處理清單和字典

到目前為止,我們每次都隻處理了一項使用者資訊:擷取使用者的輸入,再将輸入列印出來或作出應答;循環再次運作時,我們獲悉另一個輸入值并作出響應。然而,要記錄大量的 使用者和資訊,需要在while 循環中使用清單和字典。

for 循環是一種周遊清單的有效方式,但在for 循環中不應修改清單,否則将導緻Python難以跟蹤其中的元素。要在周遊清單的同時對其進行修改,可使用while 循環。通過 将while 循環同清單和字典結合起來使用,可收集、存儲并組織大量輸入,供以後檢視和顯示。

在清單之間移動元素

假設有一個清單,其中包含新注冊但還未驗證的網站使用者;驗證這些使用者後,如何将他們移到另一個已驗證使用者清單中呢?一種辦法是使用一個while 循環,在驗證使用者的同時

将其從未驗證使用者清單中提取出來,再将其加入到另一個已驗證使用者清單中。代碼可能類似于下面這樣:

# 首先,建立一個待驗證使用者清單
# 和一個用于存儲已驗證使用者的空清單
❶ unconfirmed_users = ['alice', 'brian', 'candace']
confirmed_users = []
# 驗證每個使用者,直到沒有未驗證使用者為止
# 将每個經過驗證的清單都移到已驗證使用者清單中 
❷ while unconfirmed_users:
		current_user = unconfirmed_users.pop()
		print("Verifying user: " + current_user.title())
		confirmed_users.append(current_user)
# 顯示所有已驗證的使用者
print("\nThe following users have been confirmed:") 
for confirmed_user in confirmed_users:
	print(confirmed_user.title())
           

我們首先建立了一個未驗證使用者清單(見❶),其中包含使用者Alice、Brian和Candace,還建立了一個空清單,用于存儲已驗證的使用者。❷處的while 循環将不斷地運作,直到列 表unconfirmed_users 變成空的。在這個循環中,❸處的函數pop() 以每次一個的方式從清單unconfirmed_users 末尾删除未驗證的使用者。由于Candace位于列 表unconfirmed_users 末尾,是以其名字将首先被删除、存儲到變量current_user 中并加入到清單confirmed_users 中(見❹)。接下來是Brian,然後是Alice。

為模拟使用者驗證過程,我們列印一條驗證消息并将使用者加入到已驗證使用者清單中。未驗證使用者清單越來越短,而已驗證使用者清單越來越長。未驗證使用者清單為空後結束循環,再 列印已驗證使用者清單:

Verifying user: Candace 
Verifying user: Brian 
Verifying user: Alice

The following users have been confirmed: 
Candace
Brian
Alice
           

删除包含特定值得所有清單元素

在第3章中,我們使用函數remove() 來删除清單中的特定值,這之是以可行,是因為要删除的值在清單中隻出現了一次。如果要删除清單中所有包含特定值的元素,該怎麼辦

呢?

假設你有一個寵物清單,其中包含多個值為’cat’ 的元素。要删除所有這些元素,可不斷運作一個while 循環,直到清單中不再包含值’cat’ ,如下所示:

pets = ['dog', 'cat', 'dog', 'goldfish', 'cat', 'rabbit', 'cat'] 
print(pets)

while 'cat' in pets: 
	pets.remove('cat')
	
print(pets)
           

我們首先建立了一個清單,其中包含多個值為’cat’ 的元素。列印這個清單後,Python進入while 循環,因為它發現’cat’ 在清單中至少出現了一次。進入這個循環後,Python 删除第一個’cat’ 并傳回到while 代碼行,然後發現’cat’ 還包含在清單中,是以再次進入循環。它不斷删除’cat’ ,直到這個值不再包含在清單中,然後退出循環并再次打 印清單:

['dog', 'cat', 'dog', 'goldfish', 'cat', 'rabbit', 'cat'] 
['dog', 'dog', 'goldfish', 'rabbit']
           

使用使用者輸入來填充字典

可使用while循環提示使用者輸入任意數量的資訊。下面來建立一個調查程式,其中的循環每次執行時都提示輸入被調查者的名字和回答。我們将收集的資料存儲在一個字典中,以

便将回答同被調查者關聯起來:

responses = {}
# 設定一個标志,指出調查是否繼續 
polling_active = True
while polling_active:
	# 提示輸入被調查者的名字和回答
	name = input("\nWhat is your name? ")
	response = input("Which mountain would you like to climb someday? ")
	# 将答卷存儲在字典中 
	responses[name] = response
	# 看看是否還有人要參與調查
	repeat = input("Would you like to let another person respond? (yes/ no) ")
	if repeat == 'no': 
		polling_active = False
		
# 調查結束,顯示結果
print("\n--- Poll Results ---")
for name, response in responses.items():
	print(name + " would like to climb " + response + ".")
           

這個程式首先定義了一個空字典(responses ),并設定了一個标志(polling_active ),用于指出調查是否繼續。隻要polling_active 為True ,Python就運 行while 循環中的代碼。

在這個循環中,提示使用者輸入其使用者名及其喜歡爬哪座山(見❶)。将這些資訊存儲在字典responses 中(見❷),然後詢問使用者調查是否繼續(見❸)。如果使用者輸入yes ,程式将再次進入while 循環;如果使用者輸入no ,标志polling_active 将被設定為False ,而while 循環将就此結束。最後一個代碼塊(見❹)顯示調查結果。

如果你運作這個程式,并輸入一些名字和回答,輸出将類似于下面這樣:

What is your name? Eric
Which mountain would you like to climb someday? Denali 
Would you like to let another person respond? (yes/ no) yes

What is your name? Lynn
Which mountain would you like to climb someday? Devil's Thumb 
Would you like to let another person respond? (yes/ no) no

--- Poll Results ---
Lynn would like to climb Devil's Thumb. 
Eric would like to climb Denali.
           

歡迎大家一起讨論交流學習,

我的 github 期待你的關注