這篇文章收集了我在Python新手開發(fā)者寫的代碼中所見到的不規(guī)范但偶爾又很微妙的問題。本文的目的是為了幫助那些新手開發(fā)者渡過寫出丑陋的Python代碼的階段。為了照顧目標(biāo)讀者,本文做了一些簡化(例如:在討論迭代器的時(shí)候忽略了生成器和強(qiáng)大的迭代工具itertools)。
對(duì)于那些新手開發(fā)者,總有一些使用反模式的理由,我已經(jīng)嘗試在可能的地方給出了這些理由。但通常這些反模式會(huì)造成代碼缺乏可讀性、更容易出bug且不符合Python的代碼風(fēng)格。如果你想要尋找更多的相關(guān)介紹資料,我極力推薦The Python Tutorial或Dive into Python。
迭代
range的使用
Python編程新手喜歡使用range來實(shí)現(xiàn)簡單的迭代,在迭代器的長度范圍內(nèi)來獲取迭代器中的每一個(gè)元素:
for i in range(len(alist)): print alist[i]
應(yīng)該牢記:range并不是為了實(shí)現(xiàn)序列簡單的迭代。相比那些用數(shù)字定義的for循環(huán),雖然用range實(shí)現(xiàn)的for循環(huán)顯得很自然,但是用在序列的迭代上卻容易出bug,而且不如直接構(gòu)造迭代器看上去清晰:
for item in alist: print item
range的濫用容易造成意外的大小差一(off-by-one)錯(cuò)誤,這通常是由于編程新手忘記了range生成的對(duì)象包括range的第一個(gè)參數(shù)而不包括第二個(gè),類似于java中的substring和其他眾多這種類型的函數(shù)。那些認(rèn)為沒有超出序列結(jié)尾的編程新手將會(huì)制造出bug:
# 迭代整個(gè)序列錯(cuò)誤的方法alist = ['her', 'name', 'is', 'rio']for i in range(0, len(alist) - 1): # 大小差一(Off by one)! print i, alist[i]
不恰當(dāng)?shù)厥褂胷ange的常見理由:
1. 需要在循環(huán)中使用索引。這并不是一個(gè)合理的理由,可以用以下方式代替使用索引:
for index, value in enumerate(alist): print index, value
2. 需要同時(shí)迭代兩個(gè)循環(huán),用同一個(gè)索引來獲取兩個(gè)值。這種情況下,可以用zip來實(shí)現(xiàn):
for word, number in zip(words, numbers): print word, number
3. 需要迭代序列的一部分。在這種情況下,僅需要迭代序列切片就可以實(shí)現(xiàn),注意添加必要的注釋注明用意:
for word in words[1:]: # 不包括第一個(gè)元素 print word
有一個(gè)例外:當(dāng)你迭代一個(gè)很大的序列時(shí),切片操作引起的開銷就比較大。如果序列只有10個(gè)元素,就沒有什么問題;但是如果有1000萬個(gè)元素時(shí),或者在一個(gè)性能敏感的內(nèi)循環(huán)中進(jìn)行切片操作時(shí),開銷就變得非常重要了。這種情況下可以考慮使用xrange代替range [1]。
在用來迭代序列之外,range的一個(gè)重要用法是當(dāng)你真正想要生成一個(gè)數(shù)字序列而不是用來生成索引:
|
新聞熱點(diǎn)
疑難解答
圖片精選