Python代碼規範指南-PEP 8

來源:本文是8-Python代碼樣式指南 的譯本

介紹

本文檔給出了Python代碼的編碼約定,該Python代碼包含主Python發行版中的標準庫。請參閱隨附的信息性PEP,該PEP描述了Python [1]的C實現中C代碼的樣式準則。

本文檔和PEP 257(Docstring約定)是從Guido最初的Python樣式指南文章中改編而來,並對Barry的樣式指南[2]進行了一些補充。

該樣式指南會隨着時間的流逝而發展,因爲會確定其他約定,而過去的約定會因語言本​​身的更改而過時。

許多項目都有自己的編碼風格準則。發生任何衝突時,此類項目特定的指南優先於該項目。

愚蠢的一致性是小頭腦的妖精

Guido的主要見解之一是代碼的讀取次數比編寫的次數多。此處提供的指南旨在提高代碼的可讀性,並使其在各種Python代碼中保持一致。正如PEP 20所說,“可讀性至關重要”。

樣式指南是關於一致性的。與該樣式指南的一致性很重要。項目內的一致性更爲重要。一個模塊或功能內的一致性是最重要的。

但是,要知道什麼時候不一致-有時樣式指南的建議就不適用。如有疑問,請運用最佳判斷。查看其他示例並確定最合適的方法。不要猶豫,問!

特別是:不要爲了遵守本PEP而破壞向後兼容性!

其他一些忽略特定準則的正當理由:

  1. 應用指南時,即使對於那些習慣於閱讀遵循此PEP的代碼的人,也會使代碼的可讀性降低。
  2. 爲了與周圍的代碼一致(也可能是出於歷史原因),該代碼也會破壞它(儘管這也是清理別人的混亂的機會(以真正的XP風格)。
  3. 由於所討論的代碼早於準則的引入,因此沒有其他理由修改該代碼。
  4. 當代碼需要與不支持樣式指南建議的功能的Python的較舊版本兼容時。

代碼佈局

縮進

每個縮進級別使用4個空格。

續行應使用在括號,方括號和花括號內使用Python的隱式線垂直對齊包裝的元素,或使用懸掛式縮進 [7]。使用懸掛式凹痕時,應考慮以下幾點:第一行不應有任何論點,而應使用進一步的縮進來清楚地將其區分爲延續行。

是:

<span style="color:#444444">#與打開定界符對齊。
foo = long_function_name(var_one,var_two,
                         var_three,var_four)

#添加4個空格(額外的縮進級別)以區分其他參數。
def long_function_name(
        var_one,var_two,var_three,
        var_four):
    打印(var_one)

#懸掛的縮進應添加一個水平。
foo = long_function_name(
    var_one,var_two,
    var_three,var_four)
</span>

沒有:

<span style="color:#444444">#不使用垂直對齊時,第一行的參數將被禁止。
foo = long_function_name(var_one,var_two,
    var_three,var_four)

#由於縮進無法區分,因此需要進一步縮進。
def long_function_name(
    var_one,var_two,var_three,
    var_four):
    打印(var_one)
</span>

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

可選的:

<span style="color:#444444">#懸掛的縮進*可以*縮進到4個空格以外的其他空格。
foo = long_function_name(
  var_one,var_two,
  var_three,var_four)
</span>

如果 if-語句的條件部分足夠長,可以要求將其寫成多行,則值得注意的是,兩個字符關鍵字(即if),一個空格和一個左括號的組合會產生一個自然的多行條件的後續行的4個空格縮進。這可能與嵌套在if語句內的縮進代碼集產生視覺衝突,該縮進代碼自然也將縮進4個空格。對於如何(或是否)在視覺上進一步將這些條件行與if語句內的嵌套套件區分開,PEP不做任何明確的表述。在這種情況下,可接受的選項包括但不限於:

<span style="color:#444444">#沒有額外的縮進。
如果(this_is_one_thing和
    that_is_another_thing):
    做點什麼()

#添加評論,這將在編輯器中提供一些區別
#支持語法突出顯示。
如果(this_is_one_thing和
    that_is_another_thing):
    #由於兩個條件都成立,因此我們可以進行梳理。
    做點什麼()

#在條件延續行上添加一些額外的縮進。
如果(this_is_one_thing
        和that_is_another_thing):
    做點什麼()
</span>

(另請參見下面有關是否在二進制運算符之前或之後中斷的討論。)

多行構造的右花括號/括號/括號可以在列表最後一行的第一個非空白字符下對齊,如下所示:

<span style="color:#444444">my_list = [
    1 2 3
    4 5 6
    ]
結果= some_function_that_takes_arguments(
    'a','b','c',
    'd','e','f',
    )
</span>

或者可以將其排在開始多行構造的行的第一個字符下,例如:

<span style="color:#444444">my_list = [
    1 2 3
    4 5 6
]
結果= some_function_that_takes_arguments(
    'a','b','c',
    'd','e','f',
)
</span>

製表符或空格?

空格是首選的縮進方法。

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

Python 3不允許混合使用製表符和空格進行縮進。

由製表符和空格組成的縮進的Python 2代碼應轉換爲僅使用空格。

當使用-t選項調用Python 2命令行解釋器時,它會發出有關非法混合使用製表符和空格的代碼的警告。當使用-tt時,這些警告變爲錯誤。強烈建議您使用這些選項!

最大線長

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

爲了使較長的文本塊具有較少的結構限制(文檔字符串或註釋),行長應限制爲72個字符。

通過限制所需的編輯器窗口寬度,可以並排打開多個文件,並且在使用在相鄰列中顯示兩個版本的代碼查看工具時,效果很好。

大多數工具中的默認包裝會破壞代碼的視覺結構,使其更難以理解。選擇這些限制是爲了避免在窗口寬度設置爲80的編輯器中進行換行,即使在換行時該工具在最後一列中放置了標誌符號也是如此。一些基於Web的工具可能根本不提供動態換行。

一些團隊強烈喜歡更長的線長。對於專門或主要由可以就此問題達成協議的團隊維護的代碼,可以將行長度限制增加到最多99個字符,前提是註釋和文檔字符串仍以72個字符包裝。

Python標準庫是保守的,需要將行數限制爲79個字符(文檔字符串/註釋數限制爲72個)。

包裝長行的首選方法是在括號,方括號和花括號內使用Python的隱含行連續性。通過將表達式包裝在括號中,可以將長行分成多行。應優先使用這些,而不是使用反斜槓進行行連續。

有時反斜槓可能仍然合適。例如,帶-語句的long多個不能使用隱式連續,因此可以使用反斜槓:

<span style="color:#444444">以open('/ path / to / some / file / you / want / to / read')作爲file_1,\
     以file_2的形式打開('/ path / to / some / file / being / write','w'):
    file_2.write(file_1.read())
</span>

(有關對帶有-語句的多行縮進的進一步思考,請參見前面關於多行if語句的討論。)

另一種此類情況是使用assert語句。

確保適當縮進續行。

換行符應該在二進制運算符之前還是之後?

幾十年來,推薦的樣式是二元運算符之後的突破。但是,這可能以兩種方式損害可讀性:運算符趨向於分散在屏幕上的不同列上,並且每個運算符都從其操作數移至上一行。在這裏,眼睛必須做額外的工作才能分辨出添加了哪些項目和減去了哪些項目:

<span style="color:#444444">#否:運算符的位置遠離其操作數
收入=(總工資+
          taxable_interest +
          (股息-qualified_dividends)-
          ira_deduction-
          student_loan_interest)
</span>

爲了解決此可讀性問題,數學家及其發佈者遵循相反的約定。Donald Knuth在他的“ 計算機和排版”系列中解釋了傳統規則:“儘管段落中的公式總是在二進制運算和關係之後中斷,而顯示的公式總是在二進制運算和關係之後中斷” [3]

遵循數學的傳統通常會導致代碼更具可讀性:

<span style="color:#444444">#是:易於將運算符與操作數匹配
收入=(總工資
          + taxable_interest
          +(股息-qualified_dividends)
          -ira_deduction
          -student_loan_interest)
</span>

在Python代碼中,只要約定在本地是一致的,就可以在二進制運算符之前或之後中斷。對於新代碼,建議使用Knuth的樣式。

空行

用兩個空行包圍頂級函數和類定義。

類內的方法定義由單個空白行包圍。

多餘的空行可以(分別)用於分隔相關功能組。一堆相關的單線之間(例如,一組虛擬實現)可以省略空白行。

在函數中使用空白行,以節省空間,以指示邏輯部分。

Python接受control-L(即^ L)換頁字符作爲空格;許多工具將這些字符視爲頁面分隔符,因此您可以使用它們來分隔文件相關部分的頁面。請注意,某些編輯器和基於Web的代碼查看器可能不會將control-L識別爲換頁,而是會在其位置顯示另一個標誌符號。

源文件編碼

核心Python發行版中的代碼應始終使用UTF-8(或Python 2中的ASCII)。

使用ASCII(在Python 2中)或UTF-8(在Python 3中)的文件不應具有編碼聲明。

在標準庫中,非默認編碼僅應用於測試目的,或者在註釋或文檔字符串需要提及包含非ASCII字符的作者姓名時;否則,使用\ x, \ u,\ U或\ N轉義是在字符串文字中包含非ASCII數據的首選方法。

對於Python 3.0及更高版本,標準庫規定了以下策略(請參閱PEP 3131):Python標準庫中的所有標識符務必使用純ASCII標識符,並且在可行的情況下應使用英文單詞(在許多情況下,縮寫和技術使用的術語不是英語)。此外,字符串文字和註釋也必須使用ASCII。唯一的例外是(a)測試非ASCII功能的測試用例,以及(b)作者的姓名。名稱不基於拉丁字母(latin-1,ISO / IEC 8859-1字符集)的作者必須在此字符集中提供其姓名的音譯。

鼓勵具有全球受衆的開源項目採用類似的政策。

進口貨

  • 導入通常應在單獨的行上:

    <span style="color:#444444">是:導入操作系統
         導入系統
    
    否:import sys,os
    </span>

    可以這樣說:

    <span style="color:#444444">從子流程導入Popen,PIPE
    </span>
  • 導入總是放在文件的頂部,緊隨任何模塊註釋和文檔字符串之後,以及模塊全局變量和常量之前。

    導入應按以下順序分組:

    1. 標準庫導入。
    2. 相關第三方進口。
    3. 本地應用程序/庫特定的導入。

    您應該在每組導入之間放置一個空白行。

  • 推薦絕對導入,因爲如果導入系統配置不正確(例如,程序包中的目錄最終位於sys.path時),則它們通常更具可讀性,並且通常表現更好(或至少會提供更好的錯誤消息):

    <span style="color:#444444">導入mypkg.sibling
    從mypkg導入同級
    從mypkg.sibling導入示例
    </span>

    但是,顯式相對導入是絕對導入的一種可接受的替代方法,尤其是在處理複雜的包裝佈局時,使用絕對導入會不必要地冗長:

    <span style="color:#444444">來自。進口同胞
    從.sibling導入示例
    </span>

    標準庫代碼應避免複雜的程序包佈局,並始終使用絕對導入。

    絕對不要使用隱式相對導入,並且在Python 3中已將其刪除。

  • 從包含類的模塊中導入類時,通常可以這樣:

    <span style="color:#444444">從myclass導入MyClass
    從foo.bar.yourclass導入YourClass
    </span>

    如果此拼寫引起本地名稱衝突,則應明確拼寫它們:

    <span style="color:#444444">導入myclass
    導入foo.bar.yourclass
    </span>

    並使用“ myclass.MyClass”和“ foo.bar.yourclass.YourClass”。

  • 應避免使用通配符導入(來自<module> import *),因爲通配符使名稱空間中不清楚存在哪些名稱,這會混淆讀取器和許多自動化工具。通配符導入有一個合理的用例,它是將內部接口重新發布爲公共API的一部分(例如,使用可選加速器模塊中的定義覆蓋接口的純Python實現,以及確切的定義將是事先未知)。

    以這種方式重新發布名稱時,以下有關公共和內部接口的準則仍然適用。

模塊級Dunder名稱

模塊級“dunders”(即名稱具有兩個前緣和兩個縱下劃線)如__all__,__author__,__version__等應被放置在模塊文檔字符串之後,但在任何導入語句以外 從__future__進口。Python要求將來導入必須在模塊中出現在除文檔字符串以外的任何其他代碼之前:

<span style="color:#444444">“”“這是示例模塊。

該模塊可以完成任務。
“”

來自__future__ import barry_as_FLUFL

__all__ = ['a','b','c']
__version__ ='0.1'
__author__ ='紅衣主教'

導入操作系統
導入系統
</span>

字符串引號

在Python中,單引號字符串和雙引號字符串是相同的。本PEP對此不做任何建議。選擇一條規則並堅持下去。但是,當一個字符串包含單引號或雙引號字符時,請使用另一個以避免在字符串中使用反斜槓。它提高了可讀性。

對於三引號字符串,請始終使用雙引號字符以與PEP 257中的docstring約定一致。

表達式和語句中的空白

寵物皮皮

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

  • 立即放在括號,方括號或大括號內。

    <span style="color:#444444">是:垃圾郵件(ham [1],{eggs:2})
    否:垃圾郵件(ham [1],{雞蛋:2})
    </span>
  • 在尾隨逗號和其後的右括號之間。

    <span style="color:#444444">是:foo =(0,)
    否:bar =(0,)
    </span>
  • 在逗號,分號或冒號之前:

    <span style="color:#444444">是:如果x == 4:打印x,y; x,y = y,x
    否:如果x == 4:打印x,y;x,y = y,x
    </span>
  • 但是,在切片中,冒號的行爲類似於二進制運算符,並且在每一側都應具有相等的數量(將其視爲優先級最低的運算符)。在擴展切片中,兩個冒號必須應用相同的間距。例外:省略slice參數時,將省略空格。

    是:

    <span style="color:#444444">ham [1:9],ham [1:9:3],ham [:9:3],ham [1 :: 3],ham [1:9:]
    ham [lower:upper],ham [lower:upper:],ham [lower :: step]
    ham [lower + offset:upper + offset]
    ham [:upper_fn(x):step_fn(x)],ham [:: step_fn(x)]
    ham [下部+偏移量:上部+偏移量]
    </span>

    沒有:

    <span style="color:#444444">ham [下部+偏移量:上部+偏移量]
    火腿[1:9],火腿[1:9],火腿[1:9:3]
    火腿[下層::上層]
    火腿[:上部]
    </span>
  • 緊接在打開括號之後,該括號開始了函數調用的參數列表:

    <span style="color:#444444">是:垃圾郵件(1)
    否:垃圾郵件(1)
    </span>
  • 在開括號之前立即開始索引或切片:

    <span style="color:#444444">是:dct ['key'] = lst [index]
    否:dct ['key'] = lst [index]
    </span>
  • 賦值(或其他)運算符周圍有多個空格,以使其與另一個對齊。

    是:

    <span style="color:#444444">x = 1
    y = 2
    long_variable = 3
    </span>

    沒有:

    <span style="color:#444444">x = 1
    y = 2
    long_variable = 3
    </span>

其他建議

  • 避免在任何地方拖尾空格。因爲它通常是不可見的,所以可能會造成混淆:例如,反斜槓後跟一個空格和一個換行符不算作行繼續標記。一些編輯器沒有保留它,並且許多項目(例如CPython本身)都具有拒絕它的預提交鉤子。

  • 始終在兩側用單個空格將這些二進制運算符圍起來:賦值(=),擴充賦值(+ =,-= 等),比較(==,<,>,!=,<>,<=, > =,在,不在,是,是不是),布爾值(和, 或,不)。

  • 如果使用優先級不同的運算符,請考慮在優先級最低的運算符周圍添加空格。使用您自己的判斷;但是,永遠不要使用一個以上的空間,並且二進制運算符的兩邊總是具有相同數量的空白。

    是:

    <span style="color:#444444">我=我+ 1
    已提交+ = 1
    x = x * 2-1
    hypot2 = x * x + y * y
    c =(a + b)*(ab)
    </span>

    沒有:

    <span style="color:#444444">i = i + 1
    已提交+ = 1
    x = x * 2-1
    hypot2 = x * x + y * y
    c =(a + b)*(a-b)
    </span>
  • 函數註釋應使用冒號的常規規則,並且如果存在,則在->箭頭周圍始終有空格。(有關功能註釋的更多信息,請參見 下面的功能註釋。)

    是:

    <span style="color:#444444">def munge(輸入:AnyStr):...
    def munge()-> PosInt:...
    </span>

    沒有:

    <span style="color:#444444">def munge(輸入:AnyStr):...
    def munge()-> PosInt:...
    </span>
  • 當用於指示關鍵字參數或用於指示未註釋的函數參數的默認值時,請不要在=號 周圍使用空格。

    是:

    <span style="color:#444444">def複數(真實,imag = 0.0):
        返回魔術(r = real,i = imag)
    </span>

    沒有:

    <span style="color:#444444">def複數(真實,imag = 0.0):
        返回魔術(r =實數,i =影像)
    </span>

    但是,在將參數註釋與默認值組合時,請在=符號周圍使用空格:

    是:

    <span style="color:#444444">def munge(sep:AnyStr =無):...
    def munge(輸入:AnyStr,sep:AnyStr =無,限制= 1000):...
    </span>

    沒有:

    <span style="color:#444444">def munge(輸入:AnyStr = None):...
    def munge(輸入:AnyStr,極限= 1000):...
    </span>
  • 通常不建議使用複合語句(同一行上的多個語句)。

    是:

    <span style="color:#444444">如果foo =='blah':
        do_blah_thing()
    do_one()
    do_two()
    do_three()
    </span>

    而不是:

    <span style="color:#444444">如果foo =='blah':do_blah_thing()
    do_one(); do_two(); do_three()
    </span>
  • 雖然有時可以將if / for / while的小主體放在同一行上是可以的,但是對於多子句語句則永遠不要這樣做。也要避免摺疊這麼長的線!

    而不是:

    <span style="color:#444444">如果foo =='blah':do_blah_thing()
    對於x in lst:總計+ = x
    當t <10時:t = delay()
    </span>

    當然不:

    <span style="color:#444444">如果foo =='blah':do_blah_thing()
    否則:do_non_blah_thing()
    
    試試:something()
    最後:cleanup()
    
    do_one(); do_two(); do_three(long,參數,
                                 列出,像這樣)
    
    如果foo =='blah':one(); 二(); 三()
    </span>

何時使用尾隨逗號

尾部的逗號通常是可選的,除了在組成一個元素的元組時它們是必需的(並且在Python 2中,它們具有print語句的語義)。爲清楚起見,建議將後者用(技術上多餘的)括號括起來。

是:

<span style="color:#444444">文件=('setup.cfg',)
</span>

好的,但是令人困惑:

<span style="color:#444444">FILES ='setup.cfg',
</span>

如果結尾的逗號多餘,則在使用版本控制系統時,當值,參數或導入項的列表預計會隨着時間擴展時,它們通常會很有用。模式是將每個值(等)單獨放在一行上,始終添加尾隨逗號,並在下一行上添加右括號/括號/括號。但是,在與結束定界符相同的行上使用尾隨逗號是沒有意義的(在上述單例元組的情況下除外)。

是:

<span style="color:#444444">文件= [
    'setup.cfg',
    “ tox.ini”,
    ]
初始化(文件,
           錯誤=正確,
           )
</span>

沒有:

<span style="color:#444444">文件= ['setup.cfg','tox.ini',]
初始化(FILES,error = True,)
</span>

註釋

與代碼矛盾的註釋比沒有註釋更糟糕。當代碼更改時,始終要始終使註釋保持最新狀態!

評論應爲完整句子。第一個單詞應大寫,除非它是一個以小寫字母開頭的標識符(請勿更改標識符的大小寫!)。

整體註釋通常由一個或多個完整句子組成的段落組成,每個句子都以句點結尾。

在多句註釋中,除了最後一句之後,您應該在句子結尾句後使用兩個空格。

編寫英語時,請遵循Strunk和White。

來自非英語國家的Python編碼人員:請用英語寫您的註釋,除非您有120%的把握確保不會說這種語言的人不會閱讀該代碼。

阻止評論

塊註釋通常適用於其後的某些(或全部)代碼,並且縮進到與該代碼相同的級別。塊註釋的每一行都以#和一個空格開頭(除非註釋內的文本是縮進的)。

塊註釋中的段落由包含單個#的行分隔。

內聯評論

謹慎使用內聯註釋。

內聯註釋是與語句在同一行上的註釋。內聯註釋應與該語句至少分隔兩個空格。它們應以#和單個空格開頭。

內聯註釋是不必要的,並且如果它們表明顯而易見,則實際上會分散注意力。不要這樣做:

<span style="color:#444444">x = x + 1#增量x
</span>

但是有時候,這很有用:

<span style="color:#444444">x = x + 1#補償邊界
</span>

文檔字符串

PEP 257中,編寫好的文檔字符串(也稱爲“文檔字符串”)的約定不朽。

  • 爲所有公共模塊,函數,類和方法編寫文檔字符串。對於非公共方法,文檔字符串不是必需的,但是您應該使用註釋來描述該方法的作用。該註釋應出現在def行之後。

  • PEP 257描述了良好的文檔字符串約定。請注意,最重要的是,多行文檔字符串結尾的“”應單獨位於一行上:

    <span style="color:#444444">“”“返回一個foobang
    
    可選的plotz說首先將bizbaz磨碎。
    “”
    </span>
  • 對於一個襯裏文檔字符串,請在最後一行保持結尾的“”“。

命名約定

Python庫的命名約定有些混亂,因此我們永遠都無法做到完全一致-儘管如此,這是當前推薦的命名標準。新的模塊和包(包括第三方框架)應按照這些標準編寫,但是在現有庫具有不同樣式的情況下,內部一致性是首選。

首要原則

對於用戶來說,作爲API公共部分可見的名稱應遵循反映用法而不是實現的約定。

描述性:命名樣式

有很多不同的命名樣式。能夠獨立於它們的用途來識別正在使用的命名樣式。

通常區分以下命名樣式:

  • b(單個小寫字母)

  • B(單個大寫字母)

  • 小寫

  • lower_case_with_underscores

  • 大寫

  • UPPER_CASE_WITH_UNDERSCORES

  • 大寫的單詞(或CapWords或CamelCase-之所以命名,是因爲其字母的顛簸外觀[4])。有時也稱爲StudlyCaps。

    注意:在CapWords中使用首字母縮寫詞時,請使用首字母縮寫詞的所有字母大寫。因此,HTTPServerError比HttpServerError好。

  • 混合大小寫(與大小寫字母首字母小寫字母不同!)

  • Capitalized_Words_With_Underscores(難看!)

還有一種使用短的唯一前綴將相關名稱組合在一起的樣式。這在Python中使用不多,但出於完整性的考慮而提及。例如,os.stat()函數返回一個元組,其元組傳統上具有諸如st_mode, st_size,st_mtime等名稱。(這樣做是爲了強調與POSIX系統調用結構的字段的對應關係,這有助於程序員熟悉該結構。)

X11庫將前導X用於其所有公共功能。在Python中,這種樣式通常被認爲是不必要的,因爲屬性和方法名稱以對象爲前綴,函數名稱以模塊名作爲前綴。

此外,還可以識別出以下使用前劃線或下劃線的特殊形式(通常可以將它們與任何大小寫慣例結合使用):

  • _single_leading_underscore:“內部使用”指標較弱。例如,從M import *不會導入名稱以下劃線開頭的對象。

  • single_trailing_underscore_:約定用於避免與Python關鍵字衝突,例如

    <span style="color:#444444">Tkinter.Toplevel(master,class _ ='ClassName')
    </span>
  • __double_leading_underscore:命名類屬性時,調用名稱修飾(在類FooBar中,__boo變爲 _FooBar__boo;請參見下文)。

  • __double_leading_and_trailing_underscore__:存在於用戶控制的名稱空間中的“魔術”對象或屬性。例如__init__,__ import__或__file__。請勿發明此類名稱;僅按記錄使用它們。

說明性:命名約定

避免使用的名稱

切勿將字符“ l”(小寫字母el),“ O”(大寫字母oh)或“ I”(大寫字母eye)用作單個字符變量名稱。

在某些字體中,這些字符與數字1和零沒有區別。當嘗試使用“ l”時,請改用“ L”。

ASCII兼容性

標準庫中使用的標識符必須 與PEP 3131策略部分中所述的ASCII兼容 。

軟件包和模塊名稱

模塊應使用簡短的全小寫名稱。如果可以提高模塊的可讀性,則可以在模塊名稱中使用下劃線。儘管不鼓勵使用下劃線,但Python軟件包也應使用短的全小寫名稱。

當用C或C ++編寫的擴展模塊具有隨附的Python模塊提供更高級別(例如,更多面向對象)的接口時,C / C ++模塊具有下劃線(例如_socket)。

類名

類名通常應使用CapWords約定。

在接口被記錄並主要用作可調用函數的情況下,可以代替使用函數的命名約定。

請注意,內置名稱有一個單獨的約定:大多數內置名稱是單個單詞(或兩個單詞一起運行),而CapWords約定僅用於異常名稱和內置常量。

類型變量名

PEP 484中引入的類型變量的名稱通常應使用CapWords,而應使用短名稱:T,AnyStr,Num。建議將後綴_co或_contra分別添加到用於聲明協變或相反行爲的變量中:

<span style="color:#444444">從輸入import TypeVar

VT_co = TypeVar('VT_co',covariant = True)
KT_contra = TypeVar('KT_contra',convariant = True)
</span>

異常名稱

因爲異常應該是類,所以此處使用類命名約定。但是,您應該在異常名稱上使用後綴“ Error”(如果異常實際上是一個錯誤)。

全局變量名

(讓我們希望這些變量只能在一個模塊內使用。)約定與函數的約定大致相同。

設計用於通過M import *使用的模塊應使用__all__機制以防止導出全局變量,或使用較早的約定在此類全局變量前加下劃線(您可能需要這樣做以表明這些全局變量是“非公開模塊” ”)。

函數和變量名

函數名稱應小寫,必要時用下劃線分隔單詞,以提高可讀性。

變量名遵循與函數名相同的約定。

僅在已經是主流樣式(例如threading.py)的上下文中才允許使用mixedCase,以保持向後兼容性。

函數和方法參數

始終將self作爲實例方法的第一個參數。

始終對類方法的第一個參數使用cls。

如果函數參數的名稱與保留關鍵字發生衝突,通常最好在其後附加一個下劃線,而不要使用縮寫或拼寫錯誤。因此,class_優於clss。(也許最好通過使用同義詞來避免此類衝突。)

方法名稱和實例變量

使用函數命名規則:小寫字母,單詞以下劃線分隔,以提高可讀性。

僅對非公共方法和實例變量使用一個前導下劃線。

爲避免名稱與子類衝突,請使用兩個前導下劃線來調用Python的名稱處理規則。

Python用類名來修飾這些名稱:如果類Foo具有名爲__a的屬性,則Foo .__ a不能訪問它。(堅持的用戶仍然可以通過調用Foo._Foo__a來獲得訪問權限。)通常,應僅使用雙引號下劃線來避免名稱與設計爲子類的類中的屬性發生衝突。

注意:關於__name的使用存在一些爭議(請參見下文)。

常數

常量通常在模塊級別定義,並以所有大寫字母書寫,並用下劃線分隔單詞。示例包括 MAX_OVERFLOW和TOTAL。

繼承設計

始終確定類的方法和實例變量(統稱爲“屬性”)應該是公共的還是非公共的。如有疑問,請選擇非公開;稍後將其公開比將公共屬性設爲不公開要容易。

公共屬性是您期望班級中不相關的客戶端使用的屬性,並承諾避免向後不兼容的更改。非公開屬性是指不打算由第三方使用的屬性;您不能保證非公共屬性不會更改,甚至不會被刪除。

我們在這裏不使用術語“私有”,因爲在Python中沒有任何屬性是真正私有的(通常沒有不必要的工作量)。

另一類屬性是屬於“子類API”(在其他語言中通常稱爲“受保護”)的那些屬性。某些類被設計爲可繼承的,以擴展或修改類行爲的各個方面。在設計這樣的類時,請務必做出明確的決定,以決定哪些屬性是公共屬性,哪些是子類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等)的方式編寫代碼。

    例如,對於形式爲+ = b 或a = a + b的語句,請不要依賴CPython有效地實現就地字符串連接。即使在CPython中,這種優化也很脆弱(僅適用於某些類型),並且在不使用引用計數的實現中根本沒有這種優化。在庫的性能敏感部分中,應改用''.join()形式。這將確保在各種實現方式中串聯發生在線性時間內。

  • 與單例(如None)的比較應始終使用 is或not進行,永遠不要使用等於運算符。

    另外,當您真正要表示x是否爲None時,要當心寫x,例如,在測試是否將默認爲None的變量或參數設置爲其他值時。另一個值可能具有在布爾上下文中可能爲false的類型(例如容器)!

  • 使用不是運算符,而不是...不是。雖然這兩個表達式在功能上相同,但前者更易讀,更可取。

    是:

    <span style="color:#444444">如果foo不是None:
    </span>

    沒有:

    <span style="color:#444444">如果不是foo爲None:
    </span>
  • 當有比較豐富排序執行的操作,最好是實現所有六個操作(__eq__,__ne__, __lt__,__le__,__gt__,__ge__)而不是依靠其他代碼,只行使特定的比較。

    爲了最大程度地減少工作量,functools.total_ordering() 裝飾器提供了一種生成缺少的比較方法的工具。

    PEP 207表明,反身性的規則由Python的假設。因此,解釋器可以將y> x與x <y交換,y> = x 與x <= y交換,並且可以交換x == y和x!= y的參數。的排序()和MIN()操作可保證使用<運算符和MAX()函數使用> 運算符。但是,最好實施所有六個操作,以免在其他情況下引起混淆。

  • 始終使用def語句而不是將lambda表達式直接綁定到標識符的賦值語句。

    是:

    <span style="color:#444444">def f(x):返回2 * x
    </span>

    沒有:

    <span style="color:#444444">f =λx:2 * x
    </span>

    第一種形式表示結果函數對象的名稱專門爲“ f”,而不是通用的“ <lambda>”。通常,這對於回溯和字符串表示形式更爲有用。使用賦值語句消除了lambda表達式相對於顯式def語句可以提供的唯一好處(即,它可以嵌入較大的表達式中)

  • 從Exception而不是BaseException派生異常。從BaseException的直接繼承保留給捕獲異常幾乎總是錯誤的事情的異常。

    基於可能需要捕獲異常的代碼的區別,而不是引發異常的位置,設計異常層次結構 。旨在回答“出了什麼問題?”的問題。以編程方式,而不是僅僅說明“發生了問題”(有關內置異常層次結構正在學習的課程的示例,請參閱PEP 3151

    類命名約定在此處適用,但是如果異常是錯誤,則應在異常類中添加後綴“ Error”。用於非本地流控制或其他形式的信令的非錯誤異常不需要特殊的後綴。

  • 適當使用異常鏈接。在Python 3中,應使用“從Y提高X”來表示顯式替換,而不會丟失原始的追溯。

    故意替換內部異常時(在Python 2中使用“提高X”或在Python 3.3+中使用“從無提高X”),請確保將相關詳細信息轉移到新的異常(例如在將KeyError轉換爲AttributeError時保留屬性名稱) ,或將原始異常的文本嵌入新的異常消息中)。

  • 在Python 2中引發異常時,請使用raise ValueError('message'), 而不是較舊的形式引發ValueValue,'message'。

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

    使用括號的形式還意味着,當異常參數很長或包含字符串格式時,由於包含括號,因此不需要使用行繼續符。

  • 捕獲異常時,請儘可能提及特定的異常,而不要使用裸露的except:子句:

    <span style="color:#444444">嘗試:
        導入platform_specific_module
    除了ImportError:
        platform_specific_module =無
    </span>

    裸除外:子句將趕上SystemExit和一個KeyboardInterrupt異常,使其更難中斷與控制-C中的程序,並能掩飾其他問題。如果要捕獲所有表示程序錯誤的異常,請使用 Exception:除外(裸除等效於BaseException:除外)。

    一個好的經驗法則是將裸'except'子句的使用限制爲兩種情況:

    1. 如果異常處理程序將打印輸出或記錄回溯;至少用戶會意識到發生了錯誤。
    2. 如果代碼需要做一些清理工作,但是讓異常通過raise向上傳播。 試試...最終 可能是處理這種情況的更好方法。
  • 在將捕獲的異常綁定到名稱時,最好使用Python 2.6中添加的顯式名稱綁定語法:

    <span style="color:#444444">嘗試:
        處理數據()
    例外除外:
        引發DataProcessingFailedError(str(exc))
    </span>

    這是Python 3中唯一支持的語法,並且避免了與較早的基於逗號的語法相關的歧義問題。

  • 捕獲操作系統錯誤時,最好使用Python 3.3中引入的顯式異常層次結構而不是對errno 值的自省。

  • 此外,對於所有try / except子句,請將try子句限制爲所需的絕對最小數量的代碼。同樣,這避免了掩蓋錯誤。

    是:

    <span style="color:#444444">嘗試:
        值=集合[鍵]
    除了KeyError:
        返回key_not_found(key)
    其他:
        返回handle_value(value)
    </span>

    沒有:

    <span style="color:#444444">嘗試:
        # 太寬泛!
        返回handle_value(collection [key])
    除了KeyError:
        #也將捕獲handle_value()引發的KeyError
        返回key_not_found(key)
    </span>
  • 當資源位於特定代碼段的本地時,請使用 with語句以確保在使用後迅速,可靠地對其進行清理。try / finally語句也是可以接受的。

  • 每當他們執行除獲取和釋放資源以外的其他操作時,都應通過單獨的函數或方法來調用上下文管理器。

    是:

    <span style="color:#444444">使用conn.begin_transaction():
        do_stuff_in_transaction(conn)
    </span>

    沒有:

    <span style="color:#444444">與conn:
        do_stuff_in_transaction(conn)
    </span>

    後面的示例沒有提供任何信息來指示__enter__和__exit__方法除了在事務處理後關閉連接外,還在做其他事情。在這種情況下,露骨很重要。

  • 在返回語句中保持一致。函數中的所有return語句應該返回一個表達式,或者都不返回。如果任何return語句返回一個表達式,則不返回任何值的任何return語句都應將其顯式聲明爲return None,並且在函數的末尾(如果可以到達)應存在一個顯式return語句。

    是:

    <span style="color:#444444">def foo(x):
        如果x> = 0:
            返回math.sqrt(x)
        其他:
            不返回
    
    def bar(x):
        如果x <0:
            不返回
        返回math.sqrt(x)
    </span>

    沒有:

    <span style="color:#444444">def foo(x):
        如果x> = 0:
            返回math.sqrt(x)
    
    def bar(x):
        如果x <0:
            返回
        返回math.sqrt(x)
    </span>
  • 使用字符串方法而不是字符串模塊。

    字符串方法總是更快,並且與unicode字符串共享相同的API。如果需要與2.0以上的Python向後兼容,請覆蓋此規則。

  • 使用''.startswith()和''.endswith()代替字符串切片來檢查前綴或後綴。

    startswith()和endswith()更乾淨,更不容易出錯:

    <span style="color:#444444">是:如果foo.startswith('bar'):
    否:如果foo [:3] =='bar':
    </span>
  • 對象類型比較應始終使用isinstance()而不是直接比較類型。

    <span style="color:#444444">是:如果isinstance(obj,int):
    
    否:如果type(obj)是type(1):
    </span>

    在檢查對象是否爲字符串時,請記住它也可能是unicode字符串!在Python 2中,str和unicode有一個通用的基類basestring,因此您可以執行以下操作:

    <span style="color:#444444">如果isinstance(obj,basestring):
    </span>

    請注意,在Python 3中,unicode和basestring不再存在(只有str),bytes對象不再是一種字符串(取而代之的是整數序列)。

  • 對於序列(字符串,列表,元組),請使用以下事實:空序列爲假。

    <span style="color:#444444">是:如果不連續:
         如果seq:
    
    否:如果len(seq):
         如果不是len(seq):
    </span>
  • 不要寫依賴大量尾隨空格的字符串文字。這種尾隨的空格在視覺上是無法區分的,因此一些編輯器(或更近期的reindent.py)會對其進行修剪。

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

    <span style="color:#444444">是:如果打招呼:
    否:如果問候==真:
    更糟:如果問候語爲真:
    </span>
  • 不鼓勵在try ... final 的final套件內使用流控制語句return / break / 繼續...,最終,流控制語句將跳到finally套件之外。這是因爲此類語句將隱式取消通過finally套件傳播的任何活動異常。

    沒有:

    <span style="color:#444444">def foo():
        嘗試:
            1/0
        最後:
            返回42
    </span>

功能註釋

隨着PEP 484的接受,功能註釋的樣式規則正在改變。

  • 爲了向前兼容,Python 3代碼中的功能註釋最好應使用PEP 484語法。(在上一節中,有一些關於註釋的格式建議。)

  • 不再鼓勵使用本PEP中先前建議的註釋樣式進行實驗。

  • 但是,在stdlib之外, 現在鼓勵在PEP 484規則之內進行實驗。例如,使用PEP 484樣式類型註釋來標記大型第三方庫或應用程序,查看添加這些註釋的難易程度,並觀察它們的存在是否增加了代碼的可理解性。

  • Python標準庫在採用此類註釋時應保持保守,但允許將其用於新代碼和大型重構。

  • 對於想要不同使用功能註釋的代碼,建議添加以下形式的註釋:

    <span style="color:#444444">#類型:忽略
    </span>

    文件頂部附近;這告訴類型檢查器忽略所有註釋。(在PEP 484中可以找到更細粒度的方法來阻止類型檢查程序的投訴。)

  • 與檢查器一樣,類型檢查器是可選的獨立工具。默認情況下,Python解釋器不應由於類型檢查而發出任何消息,也不應基於註釋更改其行爲。

  • 不想使用類型檢查器的用戶可以隨意忽略它們。但是,預期第三方庫軟件包的用戶可能希望對那些軟件包運行類型檢查器。爲此, PEP 484建議使用存根文件:類型檢查器優先於相應的.py文件讀取的.pyi文件。存根文件可以與庫一起分發,也可以通過排版的倉庫[5]單獨分發(在庫作者的允許下)。

  • 對於需要向後兼容的代碼,可以以註釋的形式添加類型註釋。參見PEP 484 [6]的相關部分 。

可變註釋

PEP 526引入了變量註釋。針對它們的樣式建議與上述功能註釋類似:

  • 模塊級變量,類和實例變量以及局部變量的註釋應在冒號後面有一個空格。

  • 冒號前不應有空格。

  • 如果賦值有一個右手邊,則等號在兩邊應恰好有一個空格。

  • 是:

    <span style="color:#444444">代碼:整數
    
    課堂要點:
        座標:元組[int,int]
        標籤:str ='<未知>'
    </span>
  • 沒有:

    <span style="color:#444444">代碼:int#冒號後沒有空格
    代碼:int#冒號前的空格
    
    類測試:
        結果:int = 0#等號周圍沒有空格
    </span>
  • 儘管PEP 526已被Python 3.6接受,但變量註釋語法是所有版本的Python上存根文件的首選語法(有關詳細信息,請參閱PEP 484)。

腳註

[7] 懸掛式縮進是一種排版樣式,其中段落中除第一行外的所有行都縮進。在Python上下文中,該術語用於描述一種樣式,其中帶括號的語句的左括號是該行的最後一個非空白字符,其後的行會縮進,直到右括號爲止。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章