第034講:豐富的else語句及簡潔的with語句
目錄
0. 請寫下這一節課你學習到的內容:格式不限,回憶並複述是加強記憶的好方式!
1. 請問以下例子中,迴圈中的 break 語句會跳過 else 語句嗎?
3. 使用什麼語句可以使你不比再擔心檔案開啟後卻忘了關閉的尷尬?
4. 使用 with 語句固然方便,但如果出現異常的話,檔案還會自動正常關閉嗎?
0. 使用 with 語句改寫以下程式碼,讓 Python 去關心檔案的開啟與關閉吧。
1. 你可以利用異常的原理,修改下面的程式碼使得更高效率的實現嗎?
0. 請寫下這一節課你學習到的內容:格式不限,回憶並複述是加強記憶的好方式!
這節課我們來談談豐富的else語句及簡潔的with語句,大多數程式語言來說,else 語句只能跟 if 語句進行搭配,但是在Python裡面,else 語句具有更加豐富的功能,在Python中,
- else語句不僅能夠跟 if 語句進行搭配,構成“要麼怎麼,要麼不怎樣”的句式
- 還能跟迴圈語句(for語句或者while語句)進行搭配,構成“幹完了能怎樣,幹不完就別想怎樣”的句式
- 還能跟異常處理進行搭配,構成“沒有問題,那就幹吧”的句式。
2中,只有迴圈完成後執行,也就是說只有迴圈順利結束才會執行else 裡面的語句,也就是說,如果迴圈中使用了break 跳出了迴圈,那麼else 裡面的語句就不會被執行。
例如:
def showMaxFactor(num): count = num // 2 while count > 1: if num % count == 0: print("%d最大的約數是%d"%(num, count)) break count -= 1 else: print("%d是素數"%num) num = int(input("請輸入一個數:")) showMaxFactor(num)
當輸入的數有約數的時候,迴圈就會break,就輸出最大約數,當輸入的是素數時,迴圈就會正常執行完,然後退出迴圈,輸出是素數。
3中,與異常處理進行搭配,實現與迴圈語句的實現類似,只要 try 語句中沒有出現任何異常,就會執行 else 語句塊裡的內容。
try:
print(int("abc"))
except ValueError as reason:
print("出錯啦:" + str(reason))
else:
print("沒有任何異常!")============ RESTART: C:/Users/XiangyangDai/Desktop/上課程式碼/34-2.py ============
出錯啦:invalid literal for int() with base 10: 'abc'
try:
print(int("123"))
except ValueError as reason:
print("出錯啦:" + str(reason))
else:
print("沒有任何異常!")
============ RESTART: C:/Users/XiangyangDai/Desktop/上課程式碼/34-2.py ============
123
沒有任何異常!
接下來是介紹 with 語句:
我們可能會覺得開啟檔案又要關閉檔案,然後我們還怕開啟的檔案會出問題,所以我們又加入了異常處理,所以這樣是不是有點煩呢,所以我們的Python提供了 with 語句,利用這個語句抽象出文件操作中頻繁使用 try—exception—finally這樣相關的細節,對檔案中使用 with 語句可以大大的減少程式碼量,再也不用擔心檔案開啟的時候忘記關閉了。
with 會自動幫你考慮檔案關閉的問題,當你的檔案不再需要用到的時候,with 語句會自動幫你關閉,那麼什麼是使用 with 語句呢?
try:
f = open('data.txt', 'w')
for each_line in f:
print(each_line)
except OSError as reason:
print("出錯啦:" + str(reason))
finally:
f.close()
上面的程式碼顯然是存在問題的,這裡使用的是read的形式,如果這麼檔案不存在的時候,那麼你這裡就試圖去關閉一個不存在的檔案物件。這裡可以使用 with 語句
try:
with open('data.txt', 'w') as f:
for each_line in f:
print(each_line)
except OSError as reason:
print("出錯啦:" + str(reason))
測試題
0.在Python中,else語句可以跟哪些語句進行搭配?
答:在Python中,else語句不僅能跟 if 語句搭配,構成“要麼怎樣,要麼不怎樣”語境;Ta 還能跟迴圈語句(for 語句或者 while 語句),構成“幹完了能怎樣,幹不完就別想怎樣”的語境;其實 else 語句還能夠跟我們剛剛講的異常處理進行搭配,構成“沒有問題,那就幹吧”的語境。
1. 請問以下例子中,迴圈中的 break 語句會跳過 else 語句嗎?
def showMaxFactor(num):
count = num // 2
while count > 1:
if num % count == 0:
print('%d最大的約數是%d' % (num, count))
break
count -= 1
else:
print('%d是素數!' % num)
num = int(input('請輸入一個數:'))
showMaxFactor(num)
答:會,因為如果將 else 語句與迴圈語句(while 和 for 語句)進行搭配,那麼只有在迴圈正常執行完成後才會執行 else 語句塊的內容。
2. 請目測以下程式碼會列印什麼內容?
try:
print('ABC')
except:
print('DEF')
else:
print('GHI')
finally:
print('JKL')
答:只有 except 語句中的內容不被列印,因為 try 語句塊中並沒有異常,則 else 語句塊也會被執行。
ABC
GHI
JKL
3. 使用什麼語句可以使你不比再擔心檔案開啟後卻忘了關閉的尷尬?
答:使用 with 語句。
try:
with open('data.txt', 'w') as f:
for each_line in f:
print(each_line)
except OSError as reason:
print('出錯啦:' + str(reason))
4. 使用 with 語句固然方便,但如果出現異常的話,檔案還會自動正常關閉嗎?
答:with 語句會自動處理檔案的開啟和關閉,如果中途出現異常,會執行清理程式碼,然後確保檔案自動關閉。
5. 你可以換一種形式寫出下邊的虛擬碼嗎?
with A() as a:
with B() as b:
suite
答:with 語句處理多個專案的時候,可以用逗號隔開寫成一條語句
with A() as a, B() as b:
suite
動動手
0. 使用 with 語句改寫以下程式碼,讓 Python 去關心檔案的開啟與關閉吧。
def file_compare(file1, file2):
f1 = open(file1)
f2 = open(file2)
count = 0 # 統計行數
differ = [] # 統計不一樣的數量
for line1 in f1:
line2 = f2.readline()
count += 1
if line1 != line2:
differ.append(count)
f1.close()
f2.close()
return differ
file1 = input('請輸入需要比較的頭一個檔名:')
file2 = input('請輸入需要比較的另一個檔名:')
differ = file_compare(file1, file2)
if len(differ) == 0:
print('兩個檔案完全一樣!')
else:
print('兩個檔案共有【%d】處不同:' % len(differ))
for each in differ:
print('第 %d 行不一樣' % each)
答:使用 with 語句處理檔案可以減少需要編寫的程式碼量和粗心的錯誤。
def file_compare(file1, file2):
with open(file1) as f1, open(file2) as f2:
count = 0 # 統計行數
differ = [] # 統計不一樣的數量
for line1 in f1:
line2 = f2.readline()
count += 1
if line1 != line2:
differ.append(count)
return differ
file1 = input('請輸入需要比較的頭一個檔名:')
file2 = input('請輸入需要比較的另一個檔名:')
differ = file_compare(file1, file2)
if len(differ) == 0:
print('兩個檔案完全一樣!')
else:
print('兩個檔案共有【%d】處不同:' % len(differ))
for each in differ:
print('第 %d 行不一樣' % each)
1. 你可以利用異常的原理,修改下面的程式碼使得更高效率的實現嗎?
print('|--- 歡迎進入通訊錄程式 ---|')
print('|--- 1:查詢聯絡人資料 ---|')
print('|--- 2:插入新的聯絡人 ---|')
print('|--- 3:刪除已有聯絡人 ---|')
print('|--- 4:退出通訊錄程式 ---|')
contacts = dict()
while 1:
instr = int(input('\n請輸入相關的指令程式碼:'))
if instr == 1:
name = input('請輸入聯絡人姓名:')
if name in contacts:
print(name + ' : ' + contacts[name])
else:
print('您輸入的姓名不再通訊錄中!')
if instr == 2:
name = input('請輸入聯絡人姓名:')
if name in contacts:
print('您輸入的姓名在通訊錄中已存在 -->> ', end='')
print(name + ' : ' + contacts[name])
if input('是否修改使用者資料(YES/NO):') == 'YES':
contacts[name] = input('請輸入使用者聯絡電話:')
else:
contacts[name] = input('請輸入使用者聯絡電話:')
if instr == 3:
name = input('請輸入聯絡人姓名:')
if name in contacts:
del(contacts[name]) # 也可以使用dict.pop()
else:
print('您輸入的聯絡人不存在。')
if instr == 4:
break
print('|--- 感謝使用通訊錄程式 ---|')
答:使用條件語句的程式碼非常直觀明瞭,但是效率不高。因為程式會兩次訪問字典的鍵,一次判斷是否存在(例如 if name in contacts),一次獲得值(例如 print(name + ' : ' + contacts[name]))。
如果利用異常解決方案,我們可以簡單避開每次需要使用 in 判斷是否鍵存在字典中的操作。因為只要當鍵不存在字典中時,會觸發 KeyError 異常,利用此特性我們可以修改程式碼如下:
print('|--- 歡迎進入通訊錄程式 ---|')
print('|--- 1:查詢聯絡人資料 ---|')
print('|--- 2:插入新的聯絡人 ---|')
print('|--- 3:刪除已有聯絡人 ---|')
print('|--- 4:退出通訊錄程式 ---|')
contacts = dict()
while 1:
instr = int(input('\n請輸入相關的指令程式碼:'))
if instr == 1:
name = input('請輸入聯絡人姓名:')
try:
print(name + ' : ' + contacts[name])
except KeyError:
print('您輸入的姓名不再通訊錄中!')
if instr == 2:
name = input('請輸入聯絡人姓名:')
try:
contacts[name] # 有點“為賦新詞強說愁”的感覺
print('您輸入的姓名在通訊錄中已存在 -->> ', end='')
print(name + ' : ' + contacts[name])
if input('是否修改使用者資料(YES/NO):') == 'YES':
contacts[name] = input('請輸入使用者聯絡電話:')
except KeyError:
contacts[name] = input('請輸入使用者聯絡電話:')
if instr == 3:
name = input('請輸入聯絡人姓名:')
try:
del(contacts[name]) # 也可以使用dict.pop()
except KeyError:
print('您輸入的聯絡人不存在。')
if instr == 4:
break
print('|--- 感謝使用通訊錄程式 ---|')