當前位置:
首頁 > 知識 > PEP8中文版:Python編碼風格指南

PEP8中文版:Python編碼風格指南

PEP8中文版:Python編碼風格指南

目錄

縮進

製表符還是空格?

行的最大長度

空行

源文件編碼

導入

無法忍受的

其它建議

注釋塊

行內注釋

文檔字元串

根本原則

描述:命名風格

規定:命名約定

本文檔所提供的編碼規範,適用於主要的Python發行版中組成標準庫的Python代碼。請參閱PEP關於Python的C實現的C編碼風格指南的描述[1]。

本文檔和PEP257(文檔字元串規範)改編自Guido的《Python Style Guide》一文,用Barry的風格指南[2]做一些補充。

這篇風格指南隨著時間的推移而逐漸演變,隨著語言本身的變化,過去的約定已經過時了並確定了更多新的約定。

許多項目都有自己的編碼風格指南。如果有任何衝突,優先使用該項目特定的指南。

令人討厭的小人物身上愚蠢的一致性

Guido的一個重要的見解是,代碼閱讀的次數比編寫的次數多。這裡提供的指南旨在提高代碼的可讀性,並使各種不同的Python代碼一致。如PEP20所說,「易讀性非常重要」。

風格指南是關於一致性的。與本風格指南一致很重要。項目中的一致性更重要。一個模塊或功能中的一致性最重要。

最重要的是:知道何時會不一致——有時風格指南就不適用了。懷疑時,作出你最佳的判斷。看看其他的例子,並決定什麼是最好的。不要猶豫,儘管發問!

特別地:不要只為遵從這個PEP而打破向後兼容性!

忽視既定指南的一些其他的好理由:

1、當應用指南會降低代碼的可讀性,即使對於那些習慣遵照這個PEP來閱讀代碼的人來說。

2、與周圍的代碼保持一致也會破壞它(可能是歷史原因)——雖然這也是收拾別人爛攤子的好機會(在真正的XP風格中)。

3、因為問題代碼先於指南,又沒有其它的修改理由。

4、代碼需要兼容老版本,本風格指南不建議使用的Python特性。

代碼布局

縮進

每級縮進使用4個空格。連續行應該對齊摺疊元素,無論是垂直的Python的隱式行連接圓括弧內的,中括弧內的,大括弧內的,還是使用懸掛縮進[5]。使用懸掛縮進應注意以下幾點;

第一行沒有參數並且使用更多的縮進來區別它本身和連續行。

風格良好:

PEP8中文版:Python編碼風格指南

風格不良:

PEP8中文版:Python編碼風格指南

對於連續行,4個空格規則是可選的。

可選的:

PEP8中文版:Python編碼風格指南

if語句條件塊足夠長時需要編寫多行,值得注意的是兩個字元組成的關鍵字(例如if),加上一個空格,加上開括弧為多行條件的後續行創建一個4個空格的縮進。這可以給嵌入if內的縮進語句產生視覺衝突,這也自然被縮進4個空格。這個PEP沒有明確如何(是否)進一步區分條件行和if語句內的嵌入行。這種情況下,可以接受的選項包括,但不僅限於:

PEP8中文版:Python編碼風格指南

多行結構中的結束花括弧/中括弧/圓括弧是最後一行的第一個非空白字元,如:

PEP8中文版:Python編碼風格指南

或者是最後一行的第一個字元,如:

PEP8中文版:Python編碼風格指南

製表符還是空格?

空格是縮進方法的首選。

製表符僅用於與已經用製表符做縮進的代碼保持一致。

Python3不允許混用製表符和空格來縮進。

Python2代碼混用製表符和空格縮進,將被轉化為只使用空格。

調用Python2命令行解釋器時使用-t選項,可對代碼中非法混用製表符和空格發出警告。當使用-tt選項,警告將變成錯誤。這些選項是高度推薦的!

行的最大長度

限制所有行最多79個字元。

下垂的長塊結構限制為更少的文本(文檔字元串或注釋),行的長度應該限制在72個字元。

限制編輯器窗口寬度使得並排打開多個文件成為可能,並且使用代碼審查工具顯示相鄰列的兩個版本工作正常。

絕大多數工具的默認摺疊會破壞代碼的可視化結構,使其更難以理解。編輯器中的窗口寬度設置為80個字元。即使該工具將在最後一列中標記字形。一些基於網路的工具可能不會提供動態的自動換行。

有些團隊強烈喜歡較長的行長度。對於代碼維護完全或主要由一個團隊的,可以在這個問題上達成協議,象徵性的將行長度從80個字元增加到100個字元(有效地增加最大長度到99個字元)也是可以的,提供注釋和文檔字元串仍是72個字元。

Python標準庫採取保守做法,要求行限制到79個字元(文檔字元串/注釋到72個字元)。

摺疊長行的首選方法是在小括弧,中括弧,大括弧中使用Python隱式換行。長行可以在表達式外面使用小括弧來變成多行。連續行使用反斜杠更好。

反斜杠有時可能仍然是合適的。例如,長的多行的with語句不能用隱式續行,可以用反斜杠:

PEP8中文版:Python編碼風格指南

(為進一步思考With語句的多行縮進,見前面多行if語句的討論。)

另一個這樣的例子是assert語句。

確保適當的連續行縮進。

換行應該在二元操作符的前面還是後面?

過去二十年我們都是推薦放在二元操作符的後面。但是這種做法會以兩種方式傷害可讀性:多個二元操作符在屏幕上不在一列,另外如果你想知道對一個被操作的對象做了什麼操作,需要向上找一行。這導致你的眼睛不得不上下往返很多次才能搞清楚哪個數字是被加的,哪個數字是被減的:

PEP8中文版:Python編碼風格指南

為了解決可讀性問題,數學家和印刷業者通常是在二元操作符之前換行的。Donald Knuth在他的《計算機與排版》系列文章中解釋了這個傳統規則:「雖然寫在一段話中的公式經常在二元操作符的後面換行,但是單獨展示的公式通常是在二元操作符的前面換行。」

出於遵循數學傳統,所以我們這樣寫這段代碼將更加可讀:

PEP8中文版:Python編碼風格指南

空行

頂級函數和類的定義之間有兩行空行。

類內部的函數定義之間有一行空行。

額外的空行用來(謹慎地)分離相關的功能組。相關的行(例如:一組虛擬實現)之間不使用空行。

在函數中謹慎地使用空行來表示邏輯部分。

Python接受control-L(即^L)換頁符作為空白符;許多工具把這些字元作為分頁符,所以你可以使用它們為文件中的相關部分分頁。注意,一些編輯器和基於Web的代碼查看器可能不能識別control-L是換頁,將顯示另外的字形。

源文件編碼

Python核心發布中的代碼應該始終使用UTF-8(或Python2中用ASCII)。

文件使用ASCII(Python2中)或UTF-8(Python3中)不應有編碼聲明。

在標準庫中,非默認編碼僅用於測試目的或注釋或文檔字元串需要提及包含非ASCII字元的作者名;否則,使用x,u,U,或N是字元串中包含非ASCII數據的首先方式。

Python3.0及以上版本,為標準庫(參見PEP 3131)規定以下策略:Python標準庫中的所有標識符必須使用ASCII標識符,在可行的地方使用英文單詞(在很多例子中,使用非英文的縮寫和專業術語)。另外,字元串和注釋必須用ASCII。僅有的例外是(a)測試非ASCII的特點,(b)測試作者名。不是基於拉丁字母表的作者名必須提供一個他們名字的拉丁字母表的音譯。

開源項目面向全球,鼓勵採用統一策略。

導入

導入通常是單獨一行,例如:風格良好:

PEP8中文版:Python編碼風格指南

風格不良:

PEP8中文版:Python編碼風格指南

這樣也是可以的:

PEP8中文版:Python編碼風格指南

導入常常位於文件頂部,在模塊注釋和字元串文檔之後,在模塊的全局變數和常量之前。

導入應該按照以下順序分組:

1. 標準庫導入

2. 相關的第三方導入

3. 特定的本地應用/庫導入

在每個導入組之間放一行空行。

把任何相關__all__規範放在導入之後。

推薦絕對導入,因為它們更易讀,並且如果導入系統配置的不正確(例如當包中的一個目錄結束於sys.path)它們有更好的表現(至少給出更好的錯誤信息):

PEP8中文版:Python編碼風格指南

明確的相對導入可以用來接受替代絕對導入,特別是處理複雜包布局時,絕對導入過於冗長。

PEP8中文版:Python編碼風格指南

標準庫代碼應該避免複雜包布局並使用絕對導入。

隱式的相對導入應該永遠不被使用,並且在Python3中已經移除。

從一個包含類的模塊中導入類時,通常下面這樣是好的寫法:

PEP8中文版:Python編碼風格指南

如果這種寫法導致本地名字衝突,那麼就這樣寫:

PEP8中文版:Python編碼風格指南

並使用「myclass.MyClass」和「foo.bar.yourclass.YourClass」來訪問。

避免使用通配符導入(from <模塊名> import *),因為它們使哪些名字出現在命名空間變得不清楚,這混淆了讀者和許多自動化工具。通配符導入有一種合理的使用情況,重新發布一個內部介面作為一個公共API的一部分(例如,重寫一個純Python實現的介面,該介面定義從一個可選的加速器模塊並且哪些定義將被重寫提前並不知道)。

用這種方式重新命名,下面的有關公共和內部介面的指南仍適用。

模塊級別的內置屬性

模塊級別的內置屬性(名字有前後雙下劃線的),例如__all__, __author__, __version__,應該放置在模塊的文檔字元串後,任意import語句之前,from __future__導入除外。Python強制要求from __future__導入必須在任何代碼之前,只能在模塊級文檔字元串之後。

PEP8中文版:Python編碼風格指南

字元串引號

Python中,單引號字元串和雙引號字元串是一樣的。本PEP不建議如此。建議選擇一條規則並堅持下去。當一個字元串包含單引號字元或雙引號字元時,使用另一種字元串引號來避免字元串中使用反斜杠。這提高可讀性。

三引號字元串,與PEP 257 文檔字元串規範一致總是使用雙引號字元。

表達式和語句中的空格

無法忍受的

以下情況避免使用多餘的空格:

緊挨著小括弧,中括弧或大括弧。

PEP8中文版:Python編碼風格指南

緊挨在逗號,分號或冒號前:

PEP8中文版:Python編碼風格指南

在切片中冒號像一個二元操作符,冒號兩側的有相等數量空格(把它看作最低優先順序的操作符)。在一個擴展切片中,兩個冒號必須有相等數量的空格。例外:當一個切片參數被省略時,該空格被省略。

PEP8中文版:Python編碼風格指南

緊挨著左括弧之前,函數調用的參數列表的開始處:

PEP8中文版:Python編碼風格指南

緊挨著索引或切片開始的左括弧之前:

PEP8中文版:Python編碼風格指南

為了與另外的賦值(或其它)操作符對齊,不止一個空格。

PEP8中文版:Python編碼風格指南

其它建議

始終避免行尾空白。因為它們通常不可見,容易導致困惑:如果後面跟了一個空格,它就不是一個有效的續行符了。很多編輯器不保存行尾空白,CPython項目中也設置了commit前檢查以拒絕行尾空白的存在。

始終在這些二元操作符的兩邊放置一個空格:賦值(= ),增強賦值(+= ,-= 等),比較(== , < , > , != , <> , <= , >= ,in , not in ,is ,is not ),布爾(and ,or ,not )。

如果使用了不同優先順序的操作符,在低優先順序操作符周圍增加空格(一個或多個)。不要使用多於一個空格,二元運算符兩側空格數量相等。

PEP8中文版:Python編碼風格指南

當=符號用於指示關鍵字參數或默認參數值時,它周圍不要使用空格。

PEP8中文版:Python編碼風格指南

帶註解的函數使用正常的冒號規則,並且在->兩側增加一個空格:

PEP8中文版:Python編碼風格指南

如果參數既有注釋又有默認值,在等號兩邊增加一個空格(僅在既有注釋又有默認值時才加這個空格)。

PEP8中文版:Python編碼風格指南

不鼓勵使用複合語句(同一行有多條語句)。

PEP8中文版:Python編碼風格指南

儘管有時if/for/while的同一行跟一小段代碼,在一個多條子句的語句中不要如此。避免摺疊長行!

PEP8中文版:Python編碼風格指南

什麼時候使用尾部逗號?

尾部逗號通常都是可選的,除了一些強制的場景,比如元組在只有一個元素的時候需要一個尾部逗號。為了代碼更加清晰,元組只有一個元素時請務必用括弧括起來(語法上沒有強制要求):

PEP8中文版:Python編碼風格指南

當尾部逗號不是必須時,如果你用了版本控制系統那麼它將很有用。當列表元素、參數、導入項未來可能不斷增加時,留一個尾部逗號是一個很好的選擇。通常的用法是(比如列表)每個元素獨佔一行,然後尾部都有逗號,在最後一個元素的下一行寫閉標籤。如果你的數據結構都是寫在同一行的,就沒有必要保留尾部逗號了。

PEP8中文版:Python編碼風格指南

注釋

同代碼相矛盾的注釋比沒有注釋更差。當代碼修改時,始終優先更新注釋!

注釋應該是完整的句子。如果注釋是一個短語或句子,它的第一個單詞的首字母應該大寫,除非它是一個以小寫字母開頭的標識符(不更改標識符的情況下!)。

如果注釋很短,末尾可以不加句號。注釋塊通常由一個或多個段落組成,這些段落由完整的句子組成,並且每個句子都應該以句號結尾。

在句尾的句號後邊使用兩個空格。

寫英語注釋時,遵循斷詞和空格。

非英語國家的Python程序員:請用英語書寫注釋,除非你120%的確定,所有看你代碼的人都和你說一樣的語言。

非英語國家的Python程序員:請寫下你的意見,在英語中,除非你是120%肯定,代碼將不會被不講你的語言的人閱讀。

注釋塊

注釋塊通常適用於一些(或全部)緊跟其後的代碼,並且那些代碼應使用相同級別的縮進。注釋塊的每行以一個#和一個空格開始(除非注釋裡面的文本有縮進)。

注釋塊內的段落之間由僅包含#的行隔開。

行內注釋

謹慎地使用行內注釋。

行內注釋就是注釋和代碼在同一行,它與代碼之間至少用兩個空格隔開。並且它以#和一個空格開始。

如果行內注釋指出的是顯而易見,那麼它就是不必要的。 不要這樣做:

PEP8中文版:Python編碼風格指南

但有時,這樣是有用的:

PEP8中文版:Python編碼風格指南

文檔字元串

編寫好的文檔字元串(即「代碼」)約定在PEP 257中是永存的。

為所有公共模塊,函數,類和方法書寫文檔字元串。對非公開的方法書寫文檔字元串是沒有必要的,但應該寫注釋描述這個方法是做什麼的。這些注釋應該寫在def行後面。

PEP 257描述了好的文檔字元串約定。最重要的是,多行文檔字元串以一行"""結束,例如:

PEP8中文版:Python編碼風格指南

對於只有一行的文檔字元串,"""同一行上。

命名規範

Python庫的命名規範有點兒混亂,所以我們不會將他們變得完全一致——不過,這是目前推薦的命名標準。新模塊和包(包括第三方框架)應該按這些標準書寫,但對有不同的風格的已有庫,保持內部一致性是首選。

根本原則

用戶可見的API的公開部分的名稱,應該遵循反映用法而不是實現的約定。

描述:命名風格

有很多不同的命名風格。它有助於識別使用了什麼樣的命名風格,這獨立於他們的作用。

下面的命名風格是最常見的:

  • b(單個小寫字母)

  • B(單個大寫字母)

  • 小寫字元串

  • 帶下劃線的小寫字元串

  • 大寫字元串

  • 帶下劃線的大寫字元串

  • 首字母大寫的字元串(或CapWords,或駝峰命名法——因其字母看起來高低不平而得名[3])。這有時也被稱為StudlyCaps。

注意:當CapWords中使用縮寫,大寫所有的縮寫字母。因此HTTPServerError優於HttpServerError。

  • 混用大小寫的字元串(與首字母大寫字元串不同的是它以小寫字母開頭)

  • 帶下劃線的首字母大寫字元串(令人厭惡的!)

還有一種風格,使用簡短獨特的前綴組織相關的名字在一起。Python中很少這樣用,提一下是為了文檔的完整性。例如,os.stat函數返回一個元祖,它的元素名字通常類似st_mode,st_size,st_mtime等等這樣。(這樣做是為了強調與POSIX系統調用結構體一致,這有助於程序員熟悉這些。)

X11庫的所有的公開函數以X開頭。Python中,這種風格通常認為是不必要的,因為屬性名和函數名以對象名作前綴,而函數名以模塊名作前綴。

另外,以下特殊形式,前導或後置下劃線是公認的(一般可以與任何約定相結合):

  • 單前導下劃線:弱「內部使用」標誌。例如 from M import *不會導入以下劃線開頭的對象。

  • 單後置下劃線:按慣例使用避免與Python關鍵字衝突,例如。

Tkinter.Toplevel(master, class_="ClassName")

  • 雙前導下劃線:當命名類屬性,調用時名稱改編(類FooBar中,__boo變成 _FooBar__boo;見下文)。

  • 前導和後置都是雙下劃線:存在於用戶控制的命名空間的「神奇」的對象或屬性。

例如:__init__,__import__或__file__。不要創造這樣的名字;僅像文檔中那樣使用他們。

規定:命名約定

避免採用的名字

不要使用字元『l』(小寫字母el),『O』(大寫字母oh)或『I』(大寫字母eye)作為單字元變數名。

在某些字體中,這些字元與數字1和0是沒有區別的。當想使用『l』時,用『L』代替。

包名和模塊名

模塊名應該短,所有的字母小寫。可以在模塊名中使用下劃線來提高可讀性。Python包名也應該短,所有的字母小寫,不鼓勵使用下劃線。

當一個C或C++書寫的擴展模塊,伴隨Python模塊來提供了一個更高層次(例如更面向對象)的介面時,C/C++模塊名有一個前導下劃線(如_socket)。

類名

類名通常使用首字母大寫字元串的規則。

函數的命名規則 主要用來可調用的。

在介面被記錄並且主要用作調用的情況下,用函數的命名規則來代替類名的命名規則。

注意內置名有一個單獨的規則:大多數的內置名是一個單詞(或兩個單詞一起),首字母大寫字元串的規則僅用於異常名和內置常量。

類型變數名稱

類型變數名稱應該首字母大寫,並且盡量短,比如:T, AnyStr, Num。對於協變數和有協變行為的變數,建議添加後綴__co或者__contra。

PEP8中文版:Python編碼風格指南

異常名

因為異常應該是類,所以類的命名規則在這裡也同樣適用。然而,異常名(如果這個異常確實是一個錯誤)應該使用後綴「Error」。

全局變數名

(希望這些變數是在一個模塊內使用。)這些規則和那些有關函數的規則是相同的。

模塊設計為通過from M import *來使用,應使用__all__機制防止導出全局變數,或使用加前綴的舊規則,為全局變數加下劃線(可能你像表明這些全局變數是「非公開模塊」)。

函數名

函數名應該是小寫字母,必要時單詞用下劃線分開以提高可讀性。

混合大小寫僅用於這種風格已經佔主導地位的上下文(例如threading.py),以保持向後兼容性。

函數和方法參數

使用self做實例化方法的第一個參數。

使用cls做類方法的第一個參數。

如果函數的參數名與保留關鍵字衝突,最好是為參數名添加一個後置下劃線而不是使用縮寫或拼寫錯誤。

因此class_ 比clss好。(也許使用同義詞來避免更好。)。

方法名和實例變數

採用函數命名規則:小寫字母,必要時單詞用下劃線分開以提高可讀性。

僅為非公開的方法和實例變數使用一個前導下劃線。

為了避免和子類命名衝突,使用兩個前導下劃線調用Python的名稱改編規則。

Python用類名改編這些名字:如果類Foo有一個屬性名為__a,通過Foo.__a不能訪問。(可以通過調用Foo._Foo__a來訪問。)通

常,兩個前導下劃線僅用來避免與子類的屬性名衝突。

注意:關於__names的使用存在一些爭論(見下文)。

常量

常量通常定義於模塊級別並且所有的字母都是大寫,單詞用下劃線分開。例如MAX_OVERFLOW和TOTAL。

繼承的設計

確定類的方法和實例變數(統稱為:「屬性」)是否公開。如果有疑問,選擇非公開;之後把其變成公開比把一個公開屬性改成非公開要容易。

公開屬性是那些你期望與你的類不相關的客戶使用的,根據你的承諾來避免向後不兼容的變更。非公開屬性是那些不打算被第三方使用的;你不保證非公開屬性不會改變甚至被刪除。

非公共屬性是那些不打算被第三方使用的,你不能保證非公開的屬性不會改變甚至被刪除。

此處沒有使用術語「private」,因為Python中沒有真正私有的屬性(沒有通常的不必要的工作)。

屬性的另一個類別是「API子集」的一部分(在其它語言常被稱為「protected」)。某些類被設計為基類,要麼擴展,要麼修改某些方面的類的行為。在設計這樣的類的時候,要注意明確哪些屬性是公開的,哪些是API子類的一部分,哪些是真正只在你的基類中使用。

清楚這些之後,這是Python特色的指南:

  • 公開屬性沒有前導下劃線。

  • 如果公開屬性名和保留關鍵字衝突,給屬性名添加一個後置下劃線。這比縮寫或錯誤拼寫更可取。(然而,儘管有這樣的規定,對於任何類的變數或參數,特別是類方法的第一個參數,『cls』是首選的拼寫方式)

注1:參見上面對類方法的參數名的建議。

  • 對於簡單的公開數據屬性,最好只暴露屬性名,沒有複雜的訪問器/修改器方法。記住,Python為未來增強提供了一條簡單的途徑,你應該發現簡單的數據屬性需要增加功能行為。在這種情況下,使用屬性來隱藏簡單數據屬性訪問語法後面的功能實現。

注1:特性僅工作於新風格的類。

注2:盡量保持功能行為無副作用,儘管副作用如緩存通常是好的。

注3:計算開銷較大的操作避免使用特性,屬性註解使調用者相信訪問(相對)是廉價的。

  • 如果確定你的類會被子類化,並有不想子類使用的屬性,考慮用兩個前導下劃線無後置下劃線來命名它們。這將調用Python的名稱改編演算法,類名將被改編為屬性名。當子類不無意間包括相同的屬性名時,這有助於幫助避免屬性名衝突。

注1:注意改編名稱僅用於簡單類名,如果一個子類使用相同的類名和屬性名,仍然會有名字衝突。

注2:名稱改編會帶來一定的不便,如調試和__getattr__。然而,名稱改編演算法有良好的文檔,也容易手工執行。

注3:不是每個人都喜歡名稱改編。嘗試平衡避免意外的名稱衝突和高級調用者的可能。

公共和內部介面

任何向後兼容性保證只適用於公共介面。因此,重要的是用戶能夠清楚地區分公開和內部介面。

文檔介面被認為是公開的,除非文檔明確聲明他們是臨時或內部介面,免除通常的向後兼容保證。所有非文檔化的介面應假定為內部介面。

為了更好的支持自省,模塊應該使用__all__屬性顯示聲明他們公開API的名字, __all__設置為一個空列表表示該模塊沒有公開API。

即使__all__設置的適當,內部介面(包,模塊,類,函數,屬性或者其它名字)仍應以一個前導下劃線作前綴。

一個介面被認為是內部介面,如果它包含任何命名空間(包,模塊,或類)被認為是內部的。

導入名被認為是實現細節。其它模塊必須不依賴間接訪問這個導入名,除非他們是一個明確的記錄包含模塊的API的一部分,例如os.path或包的__init__模塊,從子模塊暴露功能。

程序設計建議

編寫的代碼應該不損害其他方式的Python實現(PyPy,Jython,IronPython,Cython,Psyco等等)。

例如,不要依賴CPython的高效實現字元串連接的語句形式 += b或a = a + b。這種優化即使在CPython里也是脆弱的(它只適用於某些類型),並且在不使用引用計數的實現中它完全不存在。在庫的性能易受影響的部分,應使用"".join形式。這將確保跨越不同實現的連接發生在線性時間。

與單值比如None比較使用is 或is not ,不要用等號操作符。

同樣,如果你真正的意思是if x is not None,謹防編寫if x。例如,當測試一個默認是None的變數或參數是否被置成其它的值時。這個其它值可能是在布爾上下文為假的類型(例如容器)。

使用is not 操作符而不是not...is。雖然這兩個表達式的功能相同,前者更具有可讀性並且更優。

PEP8中文版:Python編碼風格指南

當實現有豐富的比較的排序操作時,最好實現所有六個操作符(__eq__,__ne__,__lt__,__le__,__gt__,__ge__)而不是依靠其它代碼只能進行一個特定的比較。

為了減少所涉及的工作量,functools.total_ordering裝飾器提供了一個工具來生成缺失的比較函數。

PEP 207表明,Python假定自反性規則。因此,編譯器可以交換y > x和x < y,y >= x和x <= y,也可以交換參數x == y和x != y。sort和min操作保證使用< 操作符並且max功能使用> 操作符。不管怎樣,最好實現所有六個操作,這樣在其它上下文就不會產生混淆了。

使用def語句而不是使用賦值語句將lambda表達式綁定到標識符上。

PEP8中文版:Python編碼風格指南

第一種形式意味著所得的函數對象的名稱是『f』而不是一般的『<lambda>』。這在回溯和字元串表示中更有用。賦值語句的使用消除了lambda表達式可以提供顯示def聲明的唯一好處(例如它可以嵌在更大的表達式裡面)。

從Exception而不是BaseException中派生出異常。直接繼承BaseException是保留那些捕捉幾乎總是錯的異常的。

設計異常層次結構基於區別,代碼可能需要捕獲異常,而不是捕獲產生異常的位置。旨在以編程方式回答問題「出了什麼問題?」,而不是只說「問題產生了」(參見PEP 3151對這節課學習內置異常層次結構的一個例子)

類的命名規則適用於此,只是當異常確實是錯誤的時候,需要在異常類名添加「Error」後綴。用於非本地的流控制或其他形式的信號的非錯誤的異常,不需要特殊的後綴。

適當使用異常鏈。Python3中,「raise X from Y」用來表明明確的更換而不失去原來追蹤到的信息。

當故意替換一個內部異常(Python 2中使用「raise X」而Python 3.3+中使用「raise X from None」),確保相關的細節被轉移到新的異常中(比如當轉換KeyError為AttributeError時保留屬性名,或在新的異常消息中嵌入原始異常的文本)。

Python 3中產生異常,使用raise ValueError("message")替換老的形式raise ValueError,"message"。

後一種形式是不合法的Python 3語法。

目前使用的形式意味著當異常的參數很長或包含格式化字元傳時,多虧了小括弧不必再使用續行符。

捕獲異常時,儘可能提及特定的異常,而不是使用空的except:子句。例如,使用:

PEP8中文版:Python編碼風格指南

空的except:子句將捕獲SystemExit和KeyboardInterrupt異常,這使得很難用Control-C來中斷程序,也會掩飾其它的問題。如果想捕獲會導致程序錯誤的所有異常,使用except Exception:(空異常相當於except BaseException:)

一條好的經驗法則是限制使用空『except』子句的兩種情況:

1.如果異常處理程序將列印或記錄跟蹤;至少用戶將會意識到有錯誤發生。

2.如果代碼需要做一些清理工作,但是隨後讓異常用raise拋出。處理這種情況用try...finally更好。

當用一個名字綁定捕獲異常時,更喜歡Python2.6中添加的明確的名稱綁定語法。

PEP8中文版:Python編碼風格指南

這是Python3中唯一支持的語法,並避免與舊的基於逗號的語法有關的歧義問題。

捕獲操作系統異常時,更喜歡Python 3.3引進的明確的異常層次,通過errno值自省。

另外,對於所有的try/except子句,限制try子句到必須的絕對最少代碼量。這避免掩蓋錯誤。

PEP8中文版:Python編碼風格指南

當一個資源是一個局部特定的代碼段,它使用後用with語句確保迅速可靠的將它清理掉。也可以使用try/finally語句。

無論何時做了除了獲取或釋放資源的一些操作,應該通過單獨的函數或方法調用上下文管理器。例如:

PEP8中文版:Python編碼風格指南

後者的例子沒有提供任何信息表明__enter__和__exit__方法做了什麼除了事務結束後關閉連接。 在這種情況下,明確是很重要的。

返回語句保持一致。函數中的所有返回語句都有返回值,或都沒有返回值。如果任意一個返回語句有返回值,那麼任意沒有返回值的返回語句應該明確指出return None,並且明確返回語句應該放在函數結尾(如果可以)。

PEP8中文版:Python編碼風格指南

使用字元串方法代替string模塊。

字元串方法總是更快並且與unicode字元串使用相同的API。如果必須向後兼容Python2.0以前的版本,無視這個原則。

使用「.startswith 」和「.endswith」代替字元串切片來檢查前綴和後綴。

startswith和endswith更清晰,並且減少錯誤率。例如:

PEP8中文版:Python編碼風格指南

對象類型的比較使用isinstance代替直接比較類型。

PEP8中文版:Python編碼風格指南

當檢查一個對象是否是字元串時,牢記它也可能是一個unicode字元串!Python 2中,str和unicode有共同的基類basestring,所以你可以這麼做:

PEP8中文版:Python編碼風格指南

注意,Python3中, unicode和basestring不再存在(只有str),並且位元組對象不再是string(而是一個integers序列)

對於序列(字元串,列表,元組),利用空序列是false的事實。

PEP8中文版:Python編碼風格指南

不要書寫依賴後置空格的字元串。這些後置空格在視覺上無法區分,並且有些編輯器(或最近,reindent.py)將去掉他們。

不要用==來將布爾值與True或False進行比較。

PEP8中文版:Python編碼風格指南

Python標準庫不使用函數註解,由於它將給一個特定的注釋風格造成過早的承諾。相反,注釋是留給用戶去發現和試驗的有用的注釋樣式。

建議第三方實驗注釋使用一個相關的修飾符表明解釋器如果解釋註解來試驗註解。

早期的核心開發人員嘗試使用顯示不一致的函數註解,特別的注釋風格。例如:

[str]是模糊的,它是代表一個字元串列表還是一個可以是str或None的值。

符號open(file:(str,bytes))被用於值是 bytes或str替代包含一個str緊跟一個bytes值的二元元組。

seek(whence:int)註解展示出了一個規定外和規範內的混合:int限制太多(任何與__index__將被允許),它還不夠嚴格(只有值0,1,和2是允許的)。同樣的,write(b:bytes)註解也有太多限制(任何支持緩衝協議的將被允許)。

有些註解如read1(n:int=None)是自相矛盾的因為None不是一個int值。有些註解如assource_path(self,fullname:str) -> object,令人困惑它的返回類型是什麼。

除了以上的,註解在具體類型和抽象類型的使用上是不一致的:int與Integral相對,set/frozenset與MutableSet/Set相對。

抽象基類的一些註解是不正確的規範。例如,set-to-set操作需要Other是另一個Set的實例而不是一個Iterable。

另一個問題是註解成為規範的一部分,但它沒有被測試。

在大多數情況下,文檔字元串已經包含了類型規範,並且比函數註解更清晰。在其餘的情況下,一旦註解被移除文檔字元串將改進。

所見到的函數註解太特別而且與一個自動類型檢查或參數驗證的連貫系統不一致。在代碼中留下這些註解將使它以後更難做出改變以便自動化工具支持。

腳註

[5]懸掛縮進是段落中除第一行之外其它所有行都縮進的格式。在Python中,這個術語用來描述左括弧括起來的語句,這行的最後非空白的字元,隨後行縮進,直到右括弧。

參考

[1]PEP 7,van Rossum寫的C編碼風格指南

[2]Barry的GNU Mailman風格指南

http://barry.warsaw.us/software/STYLEGUIDE.txt

[3]http://www.wikipedia.com/wiki/CamelCase

[4]PEP 8現代化,2013年7月http://bugs.python.org/issue18472

版權

這個文檔已經放置在公共領域。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python部落 的精彩文章:

Python包管理及構建近年來發展全景大觀
彩色化終端文本:讓Python變得更便捷

TAG:Python部落 |