1. 程式人生 > >第034講:豐富的else語句及簡潔的with語句

第034講:豐富的else語句及簡潔的with語句

目錄

0. 請寫下這一節課你學習到的內容:格式不限,回憶並複述是加強記憶的好方式!

測試題

0.在Python中,else語句可以跟哪些語句進行搭配?

1. 請問以下例子中,迴圈中的 break 語句會跳過 else 語句嗎?

2. 請目測以下程式碼會列印什麼內容?

3. 使用什麼語句可以使你不比再擔心檔案開啟後卻忘了關閉的尷尬?

4. 使用 with 語句固然方便,但如果出現異常的話,檔案還會自動正常關閉嗎?

5. 你可以換一種形式寫出下邊的虛擬碼嗎?

動動手

0. 使用 with 語句改寫以下程式碼,讓 Python 去關心檔案的開啟與關閉吧。

1. 你可以利用異常的原理,修改下面的程式碼使得更高效率的實現嗎?


0. 請寫下這一節課你學習到的內容:格式不限,回憶並複述是加強記憶的好方式!

這節課我們來談談豐富的else語句及簡潔的with語句,大多數程式語言來說,else 語句只能跟 if 語句進行搭配,但是在Python裡面,else 語句具有更加豐富的功能,在Python中,

  1. else語句不僅能夠跟 if 語句進行搭配,構成“要麼怎麼,要麼不怎樣”的句式
  2. 還能跟迴圈語句(for語句或者while語句)進行搭配,構成“幹完了能怎樣,幹不完就別想怎樣”的句式
  3. 還能跟異常處理進行搭配,構成“沒有問題,那就幹吧”的句式。

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('|--- 感謝使用通訊錄程式 ---|')