工作中寫了個Python的子產品,CodeReview的時候被告知有些不符合Python規範的地方。于是找到了PEP8的全文(http://www.python.org/dev/peps/pep-0008/)閱讀了一番,還是受益匪淺。下面是做的一些摘要。
在項目中保持風格的一緻性。
代碼布局
縮進
對于每一次縮進使用4個空格。使用括号、中括号、大括号進行垂直對齊,或者縮進對齊。
制表符還是空格?
永遠不要将制表符與空格混合使用。 Python最常用的縮進方式是隻是用空格。 當調用Python指令行的 -t 選項時,它會檢測并警告代碼非法混合使用制表符和空格。當使用 -tt 選項時,警告變成了錯誤。
最大行長度
限制所有行最長為79個字元。 使用反斜杠來分行是一個很好的選擇。 我們應當選擇在二進制操作符之後進行分行,而不是之前。
空行
使用兩行空行來分隔頂層函數和類定義。 使用單行空行來分隔類方法定義。 在函數中使用空行來表示不同的邏輯塊。
編碼
Python核心發行代碼裡面優先使用ASCII碼或Latin-1編碼。3.0後UTF-8編碼優先于Latin-1。
導入
每一個導入通常應當使用單獨的行。 導入應當位于檔案頂部,在子產品注釋和文檔字元串之後,在全局變量和常量之前。 導入應當按以下順序分組,且每組導入之間使用空行隔開: 1、标準庫導入 2、第三方庫導入 3、本地應用程式/定制庫導入 使用絕對包路徑導入。
表達式和語句中的空格
使用兩行空行來分隔頂層函數和類定義。
注釋
誤導的注釋不如沒有注釋 注釋應當為完整的句子,且句号結尾的句子後面應當有2個空格。如果注釋很短,那麼結尾的句号可以忽略。
塊注釋
塊注釋應當和代碼縮進保持一緻。每行注釋開頭應以#開頭,然後緊跟一個空格。
塊注釋
行注釋至少和語句間隔2個空格。同樣的注釋應當以#開頭,然後緊跟一個空格。
文檔字元串
對于所有的公有子產品、類、函數和方法都需要編寫文檔字元串。 """ 作為多行的文檔字元串的結束,應該單獨一行,并且之前有一個空行。 對于隻有一行的文檔字元串來說,結尾的 """ 在同一行。 更詳細的文檔字元串規範見 PEP 257。
命名規範
目前Python庫的命名規範尚未達成一緻,但有一些推薦的标準。 在Python裡面,有一些具有特定意義的下劃線字首或者後繼的特殊格式。如: 1、 _single_leading_underscore :(單下劃線開始)弱"内部使用"訓示器。例如: from M import * 不會導入以下劃線開始的對象。 2、 single_trailing_underscore_ :(單下劃線結束)規定使用其來避免與Python關鍵字沖突,例如:
Tkinter.Toplevel(master, class_='ClassName') 在參數class後面加單下劃線,避免與關鍵字class沖突
3、__double_leading_underscore :(雙下劃線開始)命名一個類的屬性時,調用"name mangling "(類FooBar中, __boo 變為了 _FooBar__boo ; 見下文) 4、 __double_leading_and_trailing_underscore__ :(雙下劃線開始和結束)存活在使用者控制命名空間的 "magic"對象或屬性 。 例如 __init__ , __import__ 或 __file__ 。永遠不要起這樣的名字。
避免使用的命名
不要使用小寫的L、大寫的O、以及大寫的I作為單字元變量名。
包與子產品名稱
子產品應當使用簡短、全小寫的名字,也可使用下劃線連接配接來提高可讀性。 包也應當使用簡短、全小寫的名字,但不要使用下劃線。 這是由于子產品名與檔案名關聯,而在某些檔案系統中大小寫不敏感,且會截斷過長的名字。 當使用C/C++來編寫一個擴充子產品時,應當使用下劃線作為子產品名的字首。
類名
類名應當使用駝峰式(CapWords)。内部使用的類名應當加下劃線字首。
異常名
異常也是一個類,是以需要遵循類名規則。但如果你的異常确實是個錯誤的話,請使用Error字首。
全局變量名
遵循函數規則。
函數名
函數名全小寫,可以使用下劃線分隔來提高可讀性。
函數與方法參數
使用self作為執行個體方法的第一個參數。 使用cls作為類方法的第一個參數。 當函數的參數名與保留字沖突時,使用下劃線字尾(第二次提醒)。
方法名與執行個體變量
遵循函數規則。 在私有方法和執行個體變量前用單下劃線字首。 使用雙下劃線字首來調用 "name mangling "來避免與子類命名沖突。 如果類Foo有個屬性叫__a,那麼它不能使用Foo.__a讀取,但仍然可以Foo._Foo__a來讀取。
常量
常量通常在子產品級别定義,使用全大寫和下劃線分隔的形式。
繼承設計
在設計類的方法或執行個體變量時,應當覺得其實公有的還是非公有的。當不能确定時,設計為私有的。 在Python中沒有真正的私有屬性。 公有屬性不應當使用下劃線開始。 當公有屬性與保留字沖突時,在名稱後面加下劃線字尾(第三次提醒)。 對于簡單的公有屬性,最好直接通路其屬性名,而非get/set方法。
程式設計建議
代碼應當适用于Python的多個實作。比如不要依賴CPython的高效字元串語句 a+=b,而應當使用join,進而保證在不同實作上的線性開銷。 當與類似于None的單例( singleton)進行比較式,要使用is 或者 is not, 而不是使用等于操作。 當使用複雜比較實作排序操作時,最好實作全部的六個比較操作。 使用基于對象的異常。 子產品或者包應當定義自己的異常基類,這個類應當繼承自内置的Exception類。 當抛出一個異常的時候,使用 raise ValueError('message') 代替舊的 raise ValueError, 'message' 格式。這是由于當異常的參數很長或者是格式化字元串的時候,由于括号的關系,我們不需要使用多行連接配接符。 舊的格式在Python 3 中被移除。 當捕獲一個異常的時候,要用詳細的異常聲明來代替簡單的 except: 語句。 一個空的 except: 語句将會捕獲 SystemExit 和 KeyboardInterrrupt 異常。這會使得很難用Control-C來中斷一個程式,并且還會隐藏其他的問題。 另外,對于所有的try/except語句,限制 try 語句來減少必要代碼的數量。 再者,可以避免掩蓋問題。
- Yes:
No:try: value = http://www.cnblogs.com/zeutrap/archive/2012/08/29/collection[key]except KeyError: return key_not_found(key)else: return handle_value(value)
try: # 太寬了! return handle_value(collection[key])except KeyError: # 将會Catch 函數handle_value()中抛出的異常 return key_not_found(key)
使用 ''.startswith() 和 ''.endswith() 而非字元切片去檢測字首或字尾。 對象類型比較總要用 isinstance() 而非直接比較。 對于序列,(strings, lists, tuples),利用空序列為false這一點來進行判斷,而非使用長度來判斷。 别用‘==’進行布爾值和 True 或者 False 的比較。