PS:整理自書籍《Python 編寫高質量Python代碼的59個有效方法》,僅供學習整理使用
Cha 1 用Pythonic方式來思考
TIP 1 確認自己所用的Python版本
TIP 2 遵循PEP8風格指南
1.使用space來表示縮進,而不要使用tab
2.文件中的函數和類之間應該用兩行空格隔開
3.在同一個類中,各方法之間應該用一個空行隔開
4.在使用下標來獲取列表元素,調用函數或給關鍵字參數賦值的時候,不要在兩旁添加空格
5.函數變量及屬性應該用小寫字母來拼寫,各單詞之間以下劃線相連,例如,lowercase_underscore
6.受保護的實例屬性,以單個下劃線開頭,例如,_leading_underscore
7.私有的實例屬性,應該以兩個下劃線開頭,例如,__double_leading_underscore
8.類與異常,應該以每個單詞首字母均大寫的形式來命名,例如,CapitalizedWord
9.模塊級別的常量,應該全部采用大寫字母來拼寫,各個單詞之間以下劃線相連,例如。ALL_CAPS
10.類中的實例方法,應該吧首個參數命名為self,以表示該對象自身
11.類方法的首個參數,應該命名為cls,以表示該類自身。
12.每行的字符數不應超過79,可用反斜線和小括號進行多行代碼的連接
13.對于占據多行的長表達式來說,除了首行之外的其余各行都應該在通常的縮進級別上再加4個空格
14.采用內聯形式的否定詞,而不要把否定詞放在整個表達式的前面
15.不要通過檢測長度的辦法來判斷是否為空值
16.關于模塊的引入
TIP 3 了解bytes,str與unicode的區別
TIP 4 用輔助函數來取代復雜的表達式
1.開發者很容易過度運用Python的語法特性,寫出特別復雜并且難以理解的單行表達式。
2.把復雜的表達式移入輔助函數之中。
3.使用if、else表達式,比使用or或者and的Boolean操作符寫成的表達式更加清晰
TIP 5 了解切割序列的辦法
1.不要寫多余的代碼:當start索引為0,或end索引為序列長度時,應該將其省略
2.切片操作不會計較start與end是否越界
3.對list賦值的時候,如果使用切片操作,就會把原列表中處在相關范圍內的值替換成新值,即便長度不同亦可替換。
TIP 6 在單次切片操作內,不要同時指定start、end、和stride
1.既有start ,end又有 stride的切割操作,可能會令人費解。
2.盡量使用stride為正數,且不帶start或end索引
3.在同一個切片操作內,不要同時使用start,end和stride,如果確實需要執行,考慮將其拆解為兩條賦值語句,其中一條范圍切割,另一條做步進切割,或考慮使用內置itertools模塊中的islice
TIP 7 用列表推導來取代map和filter
a = [1,2,3,4,5,6,7,8]
square = [x**2 for x in a]
print(square)
1.列表推導要比內置的map和filter函數清晰,因為它無需額外編寫lambda表達式
2.列表推導可以跳過輸入列表中的某些元素,如果改用map來做就必須輔以filter方能實現
3.字典與集合也支持推導表達式
TIP 8 不要使用含有兩個以上表達式的列表推導
eg: matrix = [[1,2,3],[4,5,6],[7,8,9]]
flat = [x for row in matrix for x in row]??
squared = [[x**2 for x in row] for row in matrix]
print(flat)? # flat = [1,2,3,4,5,6,7,8,9]
print(squared) # squared = [[1,4,9],[16,25,36],[49,64,81]]
條件語句亦可加入至列表推導式
a = [1,2,3,4,5,6,7,8,9,10]
b = [x for x in a if x > 4 if x % 2 == 0]
c =??[x for x in a if x > 4 and x % 2 == 0]
此處if 和 and作用一樣,b和c的結果等價
1.列表推導支持多級循環,每一級循環也支持多項條件
2.超過兩個表達式的列表推導很難理解,應該盡量避免
TIP 9 用生成器表達式來改寫數據量較大的列表推導
列表推導的缺點:在推導過程中,對于輸入序列的每個值來說,可能都要創建僅含一項元素的全新列表,當數據非常多時,可能會消耗大量內存,導致程序崩潰。
按照列表推導的寫法寫迭代器,將中括號換成小括號,即可得到迭代器,結合next函數生成所需要的值。
eg: it = (len(x) for x in open('/tmp/my_file.txt'))
print(it)
print(next(it))
1.當輸入的數據量較大時,列表推導可能會因為占用太多內存而出問題
2.由生成器表達式所返回的迭代器,可以逐次產生輸出值,避免內存用量問題
3.把某個生成器表達式所返回的迭代器,放在另一個生成器表達式的for子表達式中,即可將二者組合起來
4.串在一起的生成器表達式執行速度很快
TIP 10 盡量用enumerate取代range
1.enumerate函數提供了一種精簡的寫法,可以在遍歷迭代器時獲知每個元素的索引
2.盡量用enumerate來改寫那種將range與下標訪問相結合的序列遍歷代碼
3.可以給enumerate提供第二個參數,以指定開始計數時所用的值(默認為0)
TIP 11 用ZIP函數同時遍歷兩個迭代器
1.內置的zip函數可以平行地遍歷多個迭代器
2.Python3的zip相當于生成器,會在遍歷過程中逐次產生元祖,而Python2中的zip則是直接把這些元祖完全生成好,并一次性返回整份列表。
3.如果提供的迭代器長度不等,那么zip就會自動提前終止
4.itertools內置模塊中的zip_longest函數可以平行遍歷多個迭代器,而不用在乎它們的長度是否相等。
TIP 12 不要在for和while循環后面寫else塊
1.Python有種特殊語法,可在for及while循環的內部語句塊之后緊跟一個else塊
2.只有當整個循環主體都沒遇到break語句時,循環后面的else塊才會執行
3.不要在循環后面使用else塊,因為這種寫法既不直觀又容易引起誤解
TIP 13 合理利用try/except/else/finally結構中的每個代碼塊
try/finally結構,確保程序能夠可靠地關閉文件句柄。
handle = open('/tmp/random_data.txt')
try:
? ? data = handle.read()
finally:
? ? handle.close()
1.無論try塊是否發生異常,都可以利用try/finally復合語句中的finally塊來執行清理工作
2.else塊可以用來縮減try塊中的代碼量,并把沒有發生異常時所要執行的語句與try/except代碼塊隔開
3.順利運行try塊后,若想使某些操作能在finally塊的清理代碼之前執行,則可將這些操作寫到else塊中。