我們都知道 Python 中else的基本用法是在條件控制語句中的 if...elif...else...
,但是 else
還有兩個其它的用途,一是用於迴圈的結尾,另一個是用在錯誤處理的 try
中。這原本是 Python 的標準語法,但由於和大部分其它程式語言的習慣不太一樣,致使人們有意或無意地忽略了這些用法。另外,對於這些用法是否符合 0x00 The Zen of Python 的原則以及該不該廣泛使用也存在很多爭議。例如在我看到的兩本書裡(Effective Python VS Write Idiomatic Python),兩位作者就分別對其持有截然不同的態度。
迴圈中的 else
跟在迴圈後面的 else
語句只有在當迴圈內沒出現 break
,也就是正常迴圈完成時才會執行。首先我們來看一個插入排序法的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
from random import randrange def insertion_sort(seq): if len(seq) 1: return seq _sorted = seq[:1] for i in seq[1:]: inserted = False for j in range(len(_sorted)): if i _sorted[j]: _sorted = [*_sorted[:j], i, *_sorted[j:]] inserted = True break if not inserted: _sorted.append(i) return _sorted print(insertion_sort([randrange(1, 100) for i in range(10)])) |
1 |
[8, 12, 12, 34, 38, 68, 72, 78, 84, 90] |
在這個例子中,對已排序的 _sorted
元素逐個與 i
進行比較,若 i
比已排序的所有元素都大,則只能排在已排序列表的最後。這時我們就需要一個額外的狀態變數 inserted
來標記完成遍歷迴圈還是中途被 break
,在這種情況下,我們可以用 else
來取代這一狀態變數:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
def insertion_sort(seq): if len(seq) 1: return seq _sorted = seq[:1] for i in seq[1:]: for j in range(len(_sorted)): if i _sorted[j]: _sorted = [*_sorted[:j], i, *_sorted[j:]] break else: _sorted.append(i) return _sorted print(insertion_sort([randrange(1, 100) for i in range(10)])) |
1 |
[1, 10, 27, 32, 32, 43, 50, 55, 80, 94] |
我認為這是一個非常酷的做法!不過要注意的是,除了 break
可以觸發後面的 else
語句,沒有迴圈的時候也會:
1 2 3 4 |
while False: print("Will never print!") else: print("Loop failed!") |
1 |
Loop failed! |
錯誤捕捉中的 else
try...except...else...finally
流程控制語法用於捕捉可能出現的異常並進行相應的處理,其中 except
用於捕捉 try
語句中出現的錯誤;而 else
則用於處理沒有出現錯誤的情況;finally
負責 try
語句的”善後工作“ ,無論如何都會執行。可以通過一個簡單的例子來展示:
1 2 3 4 5 6 7 8 9 10 11 12 |
def divide(x, y): try: result = x / y except ZeroDivisionError: print("division by 0!") else: print("result = {}".format(result)) finally: print("divide finished!") divide(5,2) print("*"*20) divide(5,0) |
1 2 3 4 5 |
result = 2.5 divide finished! ******************** division by 0! divide finished! |
當然,也可以用狀態變數的做法來替代 else
:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
def divide(x, y): result = None try: result = x / y except ZeroDivisionError: print("division by 0!") if result is not None: print("result = {}".format(result)) print("divide finished!") divide(5,2) print("*"*20) divide(5,0) |
1 2 3 4 5 |
result = 2.5 divide finished! ******************** division by 0! divide finished! |
總結
有人覺得 else
的這些用法違反直覺或者是 implicit 而非 explicit,不值得提倡。但我覺得這種”判決“需要依賴具體的應用場景以及我們對 Python 的理解,並非一定要對新人友好的語法才算是 explicit 的。當然也不推薦在所有地方都使用這個語法,for/while...else
最大的缺點在於 else
是需要與 for/file
對齊的,如果是多層巢狀或者迴圈體太長的情況,就非常不適合用 else
(回憶一下游標卡尺的梗就知道了:P)。只有在一些簡短的迴圈控制語句中,我們通過 else
擺脫一些累贅的狀態變數,這才是最 Pythonic 的應用場景!
打賞支援我寫出更多好文章,謝謝!
打賞作者
打賞支援我寫出更多好文章,謝謝!