科技改變生活 · 科技引領(lǐng)未來
導(dǎo)讀:本文會詳細(xì)介紹一個小技巧,幫助你用符合Python風(fēng)格的方式(Pythonic方式)來編寫程序。
作者:布雷特·斯拉特金(Brett Slatkin)
來源:華章科技
Python的循環(huán)有一項大多數(shù)編程語言都不支持的特性,即可以把else塊緊跟在整個循環(huán)結(jié)構(gòu)的后面。
for i in range(3):
print(&39;Loop&39;, i)
else:
print(&39;Else block!&39;)
>>>
Loop 0
Loop 1
Loop 2
Else block!
奇怪的是,程序做完整個for循環(huán)之后,竟然會執(zhí)行else塊里的內(nèi)容。既然是這樣,那為什么要叫“else”呢?這應(yīng)該叫“and”才對。在if/else結(jié)構(gòu)里,else的意思是:如果沒執(zhí)行前面那塊語句,那就執(zhí)行else塊。在try/except結(jié)構(gòu)里,except也是這個意思:如果前面那塊語句執(zhí)行失敗,那就執(zhí)行except塊。
try/except/else結(jié)構(gòu)里的else依然遵循這樣的理念,它的意思是:如果沒有異常需要處理,那就執(zhí)行這塊語句。try/finally結(jié)構(gòu)里的finally同樣很直觀,意思是:不管前面那塊代碼執(zhí)行得如何,最后都要執(zhí)行finally塊代碼。
了解了else、except、finally等在上面那些結(jié)構(gòu)里的用法,Python新手可能就覺得,for/else結(jié)構(gòu)里的else也是這個意思,即如果循環(huán)沒有從頭到尾執(zhí)行完,那就執(zhí)行else塊。實際上恰恰相反,如果循環(huán)沒有從頭到尾執(zhí)行完(也就是循環(huán)提前終止了),那么else塊里的代碼是不會執(zhí)行的。在循環(huán)中使用break語句實際上會跳過else塊。
for i in range(3):
print(&39;Loop&39;, i)
if i==1:
break
else:
print(&39;Else b1ock!&39;)
>>>
Loop 0
Loop 1
還有一個奇怪的地方是,如果對空白序列做for循環(huán),那么程序立刻就會執(zhí)行else塊。
for x in []:
print(&39;Never runs&39;)
else:
print(&39;For Else block!&39;)
>>>
For Else block!
while循環(huán)也是這樣,如果首次循環(huán)就遇到False,那么程序也會立刻運行else塊。
while False:
print(&39;Never runs&39;)
else:
print(&39;While Else block!&39;)
>>>
While Else block!
把else設(shè)計成這樣,是想讓你利用它實現(xiàn)搜索邏輯。
例如,如果要判斷兩個數(shù)是否互質(zhì)(也就是除了1之外,是不是沒有別的數(shù)能夠同時整除它們),就可以用這種結(jié)構(gòu)實現(xiàn)。先把有可能同時整除它們的數(shù)逐個試一遍,如果全都試過之后還是沒找到這樣的數(shù),那么循環(huán)就會從頭到尾執(zhí)行完(這意味著循環(huán)沒有因為break而提前跳出),然后程序就會執(zhí)行else塊里的代碼。
a = 4
b = 9
for i in range(2, min(a, b) + 1):
print(&39;Testing&39;,i)
if a % i == 0 and b % i == 0:
print(&39;Not coprime&39;)
break
else:
print(&39;Coprime&39;)
>>>
Testing 2
Testing 3
Testing 4
Coprime
實際工作中,筆者不會這樣寫,而是會改用輔助函數(shù)完成計算。這樣的輔助函數(shù)有兩種常見的寫法。
第一種寫法是,只要發(fā)現(xiàn)某個條件成立,就立刻返回,如果始終都沒碰到這種情況,那么循環(huán)就會完整地執(zhí)行,讓程序返回函數(shù)末尾的那個值作為默認(rèn)返回值。
def coprime(a, b):
for i in range(2, min(a, b) + 1):
if a % i == 0 and b % i == 0:
return False
return True
assert coprime(4, 9)
assert not coprime(3, 6)
第二種寫法是,用變量來記錄循環(huán)過程中有沒有碰到這樣的情況,如果有,那就用break提前跳出循環(huán),如果沒有,循環(huán)就會完整地執(zhí)行,無論如何,最后都返回這個變量的值。
def coprime_alternate(a, b):
is_coprime = True
for i in range(2, min(a, b) + 1):
if a % i == 0 and b % i == 0:
is_coprime = False
break
return is_coprime
assert coprime_alternate(4, 9)
assert not coprime_alternate(3, 6)
對于不熟悉for/else結(jié)構(gòu)的人來說,剛才那兩種寫法都是比較清晰的方案,大家可以根據(jù)情況選擇其中的一種。
for/else或while/else結(jié)構(gòu)本身雖然可以實現(xiàn)某些邏輯表達(dá),但它給讀者(也包括你自己)帶來的困惑,已經(jīng)蓋過了它的好處。因為for與while循環(huán)這種簡單的結(jié)構(gòu),在Python里面讀起來應(yīng)該相當(dāng)明了才對,如果把else塊緊跟在它的后面,那就會讓代碼產(chǎn)生歧義。所以,請不要這么寫。
要點
關(guān)于作者:布雷特·斯拉特金(Brett Slatkin),Google首席軟件工程師,他是Google Surveys的聯(lián)合技術(shù)創(chuàng)始人,也是PubSubHubbub協(xié)議的共同創(chuàng)造者之一。此外,Slatkin還發(fā)布了Google的第一個云計算產(chǎn)品——App Engine。早在15年前,Slatkin就開始在工作中使用Python管理Google大量的服務(wù)器群。他擁有紐約哥倫比亞大學(xué)計算機工程專業(yè)學(xué)士學(xué)位。
本文摘編自《Effective Python:編寫高質(zhì)量Python代碼的90個有效方法》(原書第2版),經(jīng)出版方授權(quán)發(fā)布。
延伸閱讀《Effective Python》(原書第2版)
推薦語:Python編程進階必讀,基于Python3.8,新增31條建議!掌握Pythonic編程方式,寫出高質(zhì)量代碼|進階到編程高手的程序員修煉之道和代碼整潔之道。
丁書明
版權(quán)所有 未經(jīng)許可不得轉(zhuǎn)載
增值電信業(yè)務(wù)經(jīng)營許可證備案號:遼ICP備14006349號
網(wǎng)站介紹 商務(wù)合作 免責(zé)聲明 - html - txt - xml