python代碼風格指南:pep8 中文翻譯

jopen 9年前發布 | 50K 次閱讀 Python開發 Python

本文給出主Python版本標準庫的編碼約定。CPython的C代碼風格參見PEP7

本文和PEP 257 文檔字符串標準改編自Guido最初的《Python Style Guide》, 并增加了Barry的GNU Mailman Coding Style Guide的部分內容。

本文會隨著語言改變等而改變。

許多項目都有自己的編碼風格指南,沖突時自己的指南為準。

一致性考慮

Guido的關鍵點之一是:代碼更多是用來讀而不是寫。本指南旨在改善Python代碼的可讀性,即PEP 20所說的“可讀性計數"(Readability counts)。

風格指南強調一致性。項目、模塊或函數保持一致都很重要。

最重要的是知道何時不一致, 有時風格指南并不適用。當有疑惑時運用你的最佳判斷,參考其他例子并多問!

特別注意:不要因為遵守本PEP而破壞向后兼容性!

部分可以違背指南情況:

  • 遵循指南會降低可讀性。

    </li>

  • 與周圍其他代碼不一致。

    </li>

  • 代碼在引入指南完成,暫時沒有理由修改。

    </li>

  • 舊版本兼容。

    </li> </ul>

    代碼布局

    縮進

    每級縮進用4個空格。

    括號中使用垂直隱式縮進或使用懸掛縮進。后者應該注意第一行要沒有參數,后續行要有縮進。

    • Yes

      </li> </ul>

      # 對準左括號
      foo = long_function_name(var_one, var_two,
                               var_three, var_four)

       不對準左括號,但加多一層縮進,以和后面內容區別。

      def long_function_name(         var_one, var_two, var_three,         var_four):     print(var_one)

       懸掛縮進必須加多一層縮進.

      foo = long_function_name(     var_one, var_two,     var_three, var_four)</pre>

      • No

        </li> </ul>

        # 不使用垂直對齊時,第一行不能有參數。
        foo = long_function_name(var_one, var_two,
            var_three, var_four)

         參數的縮進和后續內容縮進不能區別。

        def long_function_name(     var_one, var_two, var_three,     var_four):     print(var_one)</pre>

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

        # 懸掛縮進不一定是4個空格
        foo = long_function_name(
          var_one, var_two,
          var_three, var_four)

        if語句跨行時,兩個字符關鍵字(比如if)加上一個空格,再加上左括號構成了很好的縮進。后續行暫時沒有規定,至少有如下三種格式,建議使用第3種。

        # 沒有額外縮進,不是很好看,個人不推薦.
        if (this_is_one_thing and
            that_is_another_thing):
            do_something()

         添加注釋

        if (this_is_one_thing and     that_is_another_thing):     # Since both conditions are true, we can frobnicate.     do_something()

         額外添加縮進,推薦。

         Add some extra indentation on the conditional continuation line.

        if (this_is_one_thing         and that_is_another_thing):     do_something()</pre>

        右邊括號也可以另起一行。有兩種格式,建議第2種。

        # 右括號不回退,個人不推薦
        my_list = [
            1, 2, 3,
            4, 5, 6,
            ]
        result = some_function_that_takes_arguments(
            'a', 'b', 'c',
            'd', 'e', 'f',
            )

         右括號回退

        my_list = [     1, 2, 3,     4, 5, 6, ] result = some_function_that_takes_arguments(     'a', 'b', 'c',     'd', 'e', 'f', )</pre>

        空格或Tab?

        • 空格是首選的縮進方法。

          </li>

        • Tab僅僅在已經使用tab縮進的代碼中為了保持一致性而使用。

          </li>

        • Python 3中不允許混合使用Tab和空格縮進。

          </li>

        • Python 2的包含空格與Tab和空格縮進的應該全部轉為空格縮進。

          </li> </ul>

          Python2命令行解釋器使用-t選項時有非法混合Tab和空格的情況會告警。當使用-tt警告提升為錯誤。強烈推薦這些選項!另外個人推薦pep8和autopep8模塊。

          最大行寬

          限制所有行的最大行寬為79字符。

          文本長塊,比如文檔字符串或注釋,行長度應限制為72個字符。

          多數工具默認的續行功能會破壞代碼結構,使它更難理解,不推薦使用。但是超過80個字符加以提醒是必要的。一些工具可能根本不具備動態換行功能。

          一些團隊強烈希望更長的行寬。如果能達成一致,可以從從80提高到100個字符(最多99個字符)增加了標稱線的長度,不過依舊建議文檔字符串和注釋保持在72的長度。

          Python標準庫比較保守,限制行寬79個字符(文檔字符串/注釋72)。

          續行的首選方法是使用小括號、中括號和大括號反斜線仍可能在適當的時候。其次是反斜杠。比如with語句中:

          with open('/path/to/some/file/you/want/to/read') as file_1, \
               open('/path/to/some/file/being/written', 'w') as file_2:
              file_2.write(file_1.read())

          類似的還有assert。

          注意續行要盡量不影響可讀性。比如通常在二元運算符之后續行:

          class Rectangle(Blob):

              def init(self, width, height,                  color='black', emphasis=None, highlight=0):         if (width == 0 and height == 0 and                 color == 'red' and emphasis == 'strong' or                 highlight > 100):             raise ValueError("sorry, you lose")         if width == 0 and height == 0 and (color == 'red' or                                            emphasis is None):             raise ValueError("I don't think so -- values are %s, %s" %                              (width, height))         Blob.init(self, width, height,                       color, emphasis, highlight)</pre>

          空行

          • 兩行空行分割頂層函數和類的定義。

            </li>

          • 類的方法定義用單個空行分割。

            </li>

          • 額外的空行可以必要的時候用于分割不同的函數組,但是要盡量節約使用。

            </li>

          • 額外的空行可以必要的時候在函數中用于分割不同的邏輯塊,但是要盡量節約使用。

            </li>

          • Python接 contol-L作為空白符;許多工具視它為分頁符,這些要因編輯器而異。

            </li> </ul>

            源文件編碼

            在核心Python發布的代碼應該總是使用UTF-8(ASCII在Python 2)。

            ASCII文件(Python 2)或UTF-8(Python 3)不應有編碼聲明。

            標準庫中非默認的編碼應僅用于測試或當注釋或文檔字符串,比如包含非ASCII字符的作者姓名,盡量使用\x , \u , \U , or \N。

            Python 3.0及以后版本,PEP 3131可供參考,部分內容如下:在Python標準庫必須使用ASCII標識符,并盡量只使用英文字母。此外字符串和注釋也必須用ASCII。唯一的例外是:(a)測試非ASCII的功能,和(b)作者的名字不是拉丁字母。

            導入

            • 導入在單獨行

              </li> </ul>

              Yes:

              import os
              import sys
              from subprocess import Popen, PIPE

              No:

              import sys, os

              • 導入始終在文件的頂部,在模塊注釋和文檔字符串之后,在模塊全局變量和常量之前。

                </li> </ul>

                導入順序如下:標準庫進口,相關的第三方庫,本地庫。各組的導入之間要有空行。

                相關的all放在導入之后。

                • 推薦絕對路徑導入,因為它們通常更可讀,而且往往是表現更好的(或至少提供更好的錯誤消息。

                  </li> </ul>

                  import mypkg.sibling
                  from mypkg import sibling
                  from mypkg.sibling import example

                  在絕對路徑比較長的情況下,也可以使用相對路徑:

                  from . import sibling
                  from .sibling import example

                  Python 3中已經禁止隱式的相對導入。

                  • 導入類的方法:

                    </li> </ul>

                    from myclass import MyClass
                    from foo.bar.yourclass import YourClass

                    如果和本地名字有沖突:

                    import myclass
                    import foo.bar.yourclass

                    • 禁止使用通配符導入。

                      </li> </ul>

                      通配符導入(from <module> import *)應該避免,因為它不清楚命名空間有哪些名稱存,混淆讀者和許多自動化的工具。唯一的例外是重新發布對外的API時可以考慮使用。

                      字符串引用

                      Python中單引號字符串和雙引號字符串都是相同的。注意盡量避免在字符串中的反斜杠以提高可讀性。

                      根據PEP 257, 三個引號都使用雙引號。

                      表達式和語句中的空格

                      強制要求

                      • 括號里邊避免空格

                        </li> </ul>

                        # 括號里邊避免空格

                         Yes

                        spam(ham[1], {eggs: 2})

                         No

                        spam( ham[ 1 ], { eggs: 2 } )</pre>

                        • 逗號,冒號,分號之前避免空格

                          </li> </ul>

                          # 逗號,冒號,分號之前避免空格

                           Yes

                          if x == 4: print x, y; x, y = y, x

                           No

                          if x == 4 : print x , y ; x , y = y , x</pre>

                          • 索引操作中的冒號當作操作符處理前后要有同樣的空格(一個空格或者沒有空格,個人建議是沒有。

                            </li> </ul>

                            # Yes
                            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[lower + offset : upper + offset]

                             No

                            ham[lower + offset:upper + offset] ham[1: 9], ham[1 :9], ham[1:9 :3] ham[lower : : upper] ham[ : upper]</pre>

                            函數調用的左括號之前不能有空格

                            # Yes
                            spam(1)
                            dct['key'] = lst[index]

                             No

                            spam (1) dct ['key'] = lst [index]</pre>

                            • 賦值等操作符前后不能因為對齊而添加多個空格

                              </li> </ul>

                              # Yes
                              x = 1
                              y = 2
                              long_variable = 3

                               No

                              x             = 1 y             = 2 long_variable = 3</pre>

                              其他建議

                              • 二元運算符兩邊放置一個空格:

                                </li> </ul>

                                涉及 =、符合操作符 ( += , -=等)、比較( == , < , > , != , <> , <= , >= , in , not in , is , is not )、布爾( and , or , not )。

                                • 優先級高的運算符或操作符的前后不建議有空格。

                                  </li> </ul>

                                  # Yes
                                  i = i + 1
                                  submitted += 1
                                  x = x2 - 1
                                  hypot2 = xx + yy
                                  c = (a+b)  (a-b)

                                   No

                                  i=i+1 submitted +=1 x = x  2 - 1 hypot2 = x  x + y  y c = (a + b)  (a - b)</pre>

                                  • 關鍵字參數和默認值參數的前后不要加空格

                                    </li> </ul>

                                    # Yes
                                    def complex(real, imag=0.0):
                                        return magic(r=real, i=imag)

                                     No

                                    def complex(real, imag = 0.0):     return magic(r = real, i = imag)</pre>

                                    • 函數注釋中,=前后要有空格,冒號和"->"的前面無空格,后面有空格。

                                      </li> </ul>

                                      # Yes
                                      def munge(input: AnyStr):
                                      def munge(sep: AnyStr = None):
                                      def munge() -> AnyStr:
                                      def munge(input: AnyStr, sep: AnyStr = None, limit=1000):

                                       No

                                      def munge(input: AnyStr=None): def munge(input:AnyStr): def munge(input: AnyStr)->PosInt:</pre>

                                      • 通常不推薦復合語句(Compound statements: 多條語句寫在同一行)。

                                        </li> </ul>

                                        # Yes
                                        if foo == 'blah':
                                            do_blah_thing()
                                        do_one()
                                        do_two()
                                        do_three()

                                         No

                                        if foo == 'blah': do_blah_thing() do_one(); do_two(); do_three()</pre>

                                        • 盡管有時可以在if/for/while 的同一行跟一小段代碼,但絕不要跟多個子句,并盡量避免換行。

                                          </li> </ul>

                                          # No
                                          if foo == 'blah': do_blah_thing()
                                          for x in lst: total += x
                                          while t < 10: t = delay()

                                          更不是:

                                          # No
                                          if foo == 'blah': do_blah_thing()
                                          else: do_non_blah_thing()

                                          try: something() finally: cleanup()

                                          do_one(); do_two(); do_three(long, argument,                              list, like, this)

                                          if foo == 'blah': one(); two(); three()</pre>

                                          注釋

                                          與代碼自相矛盾的注釋比沒注釋更差。修改代碼時要優先更新注釋!

                                          注釋是完整的句子。如果注釋是斷句,首字母應該大寫,除非它是小寫字母開頭的標識符(永遠不要修改標識符的大小寫)。

                                          如果注釋很短,可以省略末尾的句號。注釋塊通常由一個或多個段落組成。段落由完整的句子構成且每個句子應該以點號(后面要有兩個空格)結束,并注意斷詞和空格。

                                          非英語國家的程序員請用英語書寫你的注釋,除非你120%確信代碼永遠不會被不懂你的語言的人閱讀。

                                          注釋塊

                                          注釋塊通常應用在代碼前,并和這些代碼有同樣的縮進。每行以 '# '(除非它是注釋內的縮進文本,注意#后面有空格)。

                                          注釋塊內的段落用僅包含單個 '#' 的行分割。

                                          行內注釋

                                          慎用行內注釋(Inline Comments) 節儉使用行內注釋。 行內注釋是和語句在同一行,至少用兩個空格和語句分開。行內注釋不是必需的,重復羅嗦會使人分心。不要這樣做:

                                          x = x + 1 # Increment x

                                          但有時很有必要:

                                          x = x + 1 # Compensate for border

                                          文檔字符串

                                          文檔字符串的標準參見:PEP 257

                                          • 為所有公共模塊、函數、類和方法書寫文檔字符串。非公開方法不一定有文檔字符串,建議有注釋(出現在 def 行之后)來描述這個方法做什么。

                                            </li> </ul>

                                            • 更多參考:PEP 257 文檔字符串約定。注意結尾的 """ 應該單獨成行,例如:

                                              """Return a foobang
                                              Optional plotz says to frobnicate the bizbaz first.
                                              """
                                              </li>

                                            • 單行的文檔字符串,結尾的 """ 在同一行。

                                              </li> </ul>

                                              版本標簽

                                              版本注記 (Version Bookkeeping)

                                              如果你必須在源文件中包含git、Subversion、CVS或RCS crud信息,放置在模塊的文檔字符串之后,任何其他代碼之前,上下各用一個空行:

                                              __version__ = "$Revision$"# $Source$

                                              命名約定

                                              Python庫的命名約定有點混亂,不可能完全一致。但依然有些普遍推薦的命名規范的。新的模塊和包 (包括第三方的框架) 應該遵循這些標準。對不同風格的已有的庫,建議保持內部的一致性。

                                              最重要的原則

                                              用戶可見的API命名應遵循使用約定而不是實現。

                                              描述:命名風格

                                              有多種命名風格:

                                              • b(單個小寫字母)

                                                </li>

                                              • B(單個大寫字母)

                                                </li>

                                              • lowercase(小寫串)

                                                </li>

                                              • lower_case_with_underscores(帶下劃線的小寫)

                                                </li>

                                              • UPPERCASE(大寫串)

                                                </li>

                                              • UPPER_CASE_WITH_UNDERSCORES(帶下劃線的大寫串)

                                                </li>

                                              • CapitalizedWords(首字母大寫的單詞串或駝峰縮寫)

                                                </li> </ul>

                                                注意: 使用大寫縮寫時,縮寫使用大寫字母更好。故 HTTPServerError 比 HttpServerError 更好。

                                                • mixedCase(混合大小寫,第一個單詞是小寫)

                                                  </li>

                                                • Capitalized_Words_With_Underscores(帶下劃線,首字母大寫,丑陋)

                                                  </li> </ul>

                                                  還有一種風格使用短前綴分組名字。這在Python中不常用, 但出于完整性提一下。例如,os.stat()返回的元組有st_mode, st_size, st_mtime等等這樣的名字(與POSIX系統調用結構體一致)。

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

                                                  下面講述首尾有下劃線的情況:

                                                  • _single_leading_underscore:(單前置下劃線): 弱內部使用標志。 例如"from M import " 不會導入以下劃線開頭的對象。

                                                    </li> </ul>

                                                    • single_trailing_underscore_(單后置下劃線): 用于避免與 Python關鍵詞的沖突。 例如:

                                                      </li> </ul>

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

                                                      • __double_leading_underscore(雙前置下劃線): 當用于命名類屬性,會觸發名字重整。 (在類FooBar中,__boo變成 _FooBar__boo)。

                                                        </li> </ul>

                                                        • __double_leading_and_trailing_underscore__(雙前后下劃線):用戶名字空間的魔法對象或屬性。例如:__init__ , __import__ or __file__,不要自己發明這樣的名字。

                                                          </li> </ul>

                                                          命名約定規范

                                                          • 避免采用的名字

                                                            </li> </ul>

                                                            決不要用字符'l'(小寫字母el),'O'(大寫字母oh),或 'I'(大寫字母eye) 作為單個字符的變量名。一些字體中,這些字符不能與數字1和0區別。用'L' 代替'l'時。

                                                            • 包和模塊名

                                                              </li> </ul>

                                                              模塊名要簡短,全部用小寫字母,可使用下劃線以提高可讀性。包名和模塊名類似,但不推薦使用下劃線。

                                                              模塊名對應到文件名,有些文件系統不區分大小寫且截短長名字,在 Unix上不是問題,但當把代碼遷移到 Mac、Windows 或 DOS 上時,就可能是個問題。當然隨著系統的演進,這個問題已經不是經常出現。

                                                              另外有些模塊底層用C或C++ 書寫,并有對應的高層Python模塊,C/C++模塊名有一個前置下劃線 (如:_socket)。

                                                              • 類名

                                                                </li> </ul>

                                                                遵循CapWord。

                                                                接口需要文檔化并且可以調用時,可能使用函數的命名規則。

                                                                注意大部分內置的名字是單個單詞(或兩個),CapWord只適用于異常名稱和內置的常量。

                                                                • 異常名

                                                                  </li> </ul>

                                                                  如果確實是錯誤,需要在類名添加后綴 "Error"。

                                                                  • 全局變量名

                                                                    </li> </ul>

                                                                    變量盡量只用于模塊內部,約定類似函數。

                                                                    對設計為通過 "from M import " 來使用的模塊,應采用 __all__ 機制來防止導入全局變量;或者為全局變量加一個前置下劃線。

                                                                    • 函數名

                                                                      </li> </ul>

                                                                      函數名應該為小寫,必要時可用下劃線分隔單詞以增加可讀性。 mixedCase(混合大小寫)僅被允許用于兼容性考慮(如: threading.py)。

                                                                      • 函數和方法的參數

                                                                        </li> </ul>

                                                                        實例方法第一個參數是 'self'。

                                                                        類方法第一個參數是 'cls'。

                                                                        如果函數的參數名與保留關鍵字沖突,通常在參數名后加一個下劃線。

                                                                        • 方法名和實例變量

                                                                          </li> </ul>

                                                                          同函數命名規則。

                                                                          非公開方法和實例變量增加一個前置下劃線。

                                                                          為避免與子類命名沖突,采用兩個前置下劃線來觸發重整。類Foo屬性名為__a, 不能以 Foo.__a訪問。(執著的用戶還是可以通過Foo._Foo__a。) 通常雙前置下劃線僅被用來避免與基類的屬性發生命名沖突。

                                                                          • 常量

                                                                            </li> </ul>

                                                                            常量通常在模塊級定義,由大寫字母用下劃線分隔組成。比如括MAX_OVERFLOW和TOTAL。

                                                                            • 繼承設計

                                                                              </li> </ul>

                                                                              考慮類的方法和實例變量(統稱為屬性)是否公開。如果有疑問,選擇不公開;把其改為公開比把公開屬性改為非公開要容易。

                                                                              公開屬性可供所有人使用,并通常向后兼容。非公開屬性不給第三方使用、可變甚至被移除。

                                                                              這里不使用術語"private", Python中沒有屬性是真正私有的。

                                                                              另一類屬性是子類API(在其他語言中通常稱為 "protected")。 一些類被設計為基類,可以擴展和修改。

                                                                              謹記這些Python指南:

                                                                              1. 公開屬性應該沒有前導下劃線。

                                                                                </li>

                                                                              2. 如果公開屬性名和保留關鍵字沖突,可以添加后置下劃線

                                                                                </li>

                                                                              3. 簡單的公開數據屬性,最好只公開屬性名,沒有復雜的訪問/修改方法,python的Property提供了很好的封裝方法。 d.如果不希望子類使用的屬性,考慮用兩個前置下劃線(沒有后置下劃線)命名。

                                                                                </li> </ol>

                                                                                公共和內部接口

                                                                                任何向后兼容的保證只適用于公共接口。

                                                                                文檔化的接口通常是公共的,除非明說明是臨時的或為內部接口、其他所有接口默認是內部的。

                                                                                為了更好地支持內省,模塊要在__all__屬性列出公共API。

                                                                                內部接口要有前置下劃線。

                                                                                如果命名空間(包、模塊或類)是內部的,里面的接口也是內部的。

                                                                                導入名稱應視為實現細節。其他模塊不能間接訪名字,除非在模塊的API文檔中明確記載,如os.path中或包的__init__暴露了子模塊。

                                                                                編程建議

                                                                                • 考慮多種Python實現(PyPy, Jython, IronPython,Pyrex, Psyco, 等等)。

                                                                                  </li> </ul>

                                                                                  例如,CPython對a+=b或a=a+b等語句有高效的實現,但在Jython中運行很慢,盡量改用.join()。

                                                                                  • None比較用'is'或'is not',不要用等號。

                                                                                    </li> </ul>

                                                                                    注意"if x is not None" 與"if x" 的區別。

                                                                                    • 用"is not"代替"not ... is"。前者的可讀性更好。

                                                                                      </li> </ul>

                                                                                      # Yes
                                                                                      if foo is not None

                                                                                       No

                                                                                      if not foo is None</pre>

                                                                                      • 使用基于類的異常。

                                                                                        </li> </ul>

                                                                                        比較排序操作最好是實現所有六個操作,而不是代碼中實現比較邏輯。functools.total_ordering()裝飾符可以生成缺失的比較方法。

                                                                                        __eq__,__ne__,__lt__,__lt__,__gt__,____)

                                                                                        PEP207 比較標準表明反射規則由Python完成。因此解釋器可能會交換參數的位置,比如替換y > x為x < y,所以有必要實現這5種方法。

                                                                                        • 使用函數定義def代替lambda賦值給標識符:

                                                                                          </li> </ul>

                                                                                          # Yes
                                                                                          def f(x): 
                                                                                              return 2*x

                                                                                           No

                                                                                          f = lambda x: 2*x</pre>

                                                                                          前者更適合回調和字符串表示。

                                                                                          • 異常類繼承自Exception,而不是BaseException。

                                                                                            </li> </ul>

                                                                                            源于異常,而不是BaseException例外。從BaseException直接繼承的例外情況追趕他們幾乎總是錯誤的事情做保留。

                                                                                            要設計基于層次的異常,捕捉到需要的異常,而不是異常引發的位置。能回答:“出了什么問題?”,而不是僅僅指出“問題發生”(更多參考:PEP3151 重構OS和IO異常層次

                                                                                            • 適當使用異常鏈。在Python3中"raise X from Y"明確表示更換且保留了原來的traceback。

                                                                                              </li> </ul>

                                                                                              替換內部異常(在Python2: "raise X"或"raise X from None")時,確保相關細節轉移到新的異常(如轉換KeyError為AttributeError保存屬性名,或在新的異常中嵌入原始異常)。

                                                                                              • Python2中用" raise ValueError('message')"代替"raise ValueError, 'message'"

                                                                                                </li> </ul>

                                                                                                后者不兼容Python3語法。前者續行方便。

                                                                                                • 捕獲異常時盡量指明具體異常,而不是空"except:"子句。比如:

                                                                                                  </li> </ul>

                                                                                                  # Yes
                                                                                                  try:
                                                                                                      import platform_specific_module
                                                                                                  except ImportError:
                                                                                                      platform_specific_module = None

                                                                                                  空"except:"子句(相當于except Exception)會捕捉SystemExit和KeyboardInterrupt異常,難以用Control-C中斷程序,并可掩蓋其他問題。如果 你捕捉信號錯誤之外所有的異常,使用"except Exception"。

                                                                                                  空"except:"子句適用的情況兩種情況:

                                                                                                  a, 打印出或記錄了traceback,至少讓用戶將知道已發生錯誤。 b, 代碼需要做一些清理工作,并用 raise轉發了異常。這樣try...finally可以捕捉到它。

                                                                                                  </blockquote>

                                                                                                  • Python 2.6以后建議用as顯示綁定異常名:

                                                                                                    </li> </ul>

                                                                                                    # Yes
                                                                                                    try:
                                                                                                        process_data()
                                                                                                    except Exception as exc:
                                                                                                        raise DataProcessingFailedError(str(exc))

                                                                                                    這樣才能兼容Python3語法并避免歧義。

                                                                                                    • 捕捉操作系統錯誤時,建議使用Python 3.3引入顯式異常層次,支持內省errno值。

                                                                                                      </li> </ul>

                                                                                                      • 此外所有try/except子句的代碼要盡可的少,以免屏蔽其他的錯誤。

                                                                                                        </li> </ul>

                                                                                                        # Yes
                                                                                                        try:
                                                                                                            value = collection[key]
                                                                                                        except KeyError:
                                                                                                            return key_not_found(key)
                                                                                                        else:
                                                                                                            return handle_value(value)

                                                                                                         No

                                                                                                        try:     # 太泛了!     return handle_value(collection[key]) except KeyError:     # 會捕捉到handle_value()中的KeyError     return key_not_found(key)</pre>

                                                                                                        • 本地資源建議使用with語句,以確保即時清理。當然try / finally語句也是可以接受的。

                                                                                                          </li> </ul>

                                                                                                          • 上下文管理器在做獲取和釋放資源之外的事情時,應通過獨立的函數或方法。例如:

                                                                                                            </li> </ul>

                                                                                                            # Yes
                                                                                                            with conn.begin_transaction():
                                                                                                                do_stuff_in_transaction(conn)

                                                                                                             No

                                                                                                            with conn:     do_stuff_in_transaction(conn)</pre>

                                                                                                            后者指明enter和exit方法。

                                                                                                            • 函數或者方法在沒有返回時要明確返回None。

                                                                                                              </li> </ul>

                                                                                                              # Yesdef foo(x):
                                                                                                                  if x >= 0:
                                                                                                                      return math.sqrt(x)
                                                                                                                  else:
                                                                                                                      return Nonedef bar(x):
                                                                                                                  if x < 0:
                                                                                                                      return None
                                                                                                                  return math.sqrt(x)# Nodef foo(x):
                                                                                                                  if x >= 0:
                                                                                                                      return math.sqrt(x)def bar(x):
                                                                                                                  if x < 0:
                                                                                                                      return
                                                                                                                  return math.sqrt(x)

                                                                                                              • 使用字符串方法而不是string模塊。

                                                                                                                </li> </ul>

                                                                                                                python 2.0以后字符串方法總是更快,且Unicode字符串相同的API。

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

                                                                                                                  </li> </ul>

                                                                                                                  startswith()和endswith更簡潔,利于減少錯誤。例如:

                                                                                                                  # Yes
                                                                                                                  if foo.startswith('bar'):

                                                                                                                   No

                                                                                                                  if foo[:3] == 'bar':</pre>

                                                                                                                  • 使用isinstance()代替對象類型的比較:

                                                                                                                    </li> </ul>

                                                                                                                    # Yes
                                                                                                                    if isinstance(obj, int):

                                                                                                                     No

                                                                                                                    if type(obj) is type(1):</pre>

                                                                                                                    檢查是否是字符串時,注意Python 2中str和unicode有公共的基類:

                                                                                                                    if isinstance(obj, basestring): 在 Python 2.2 中,types 模塊為此定義了 StringTypes 類型,例如:

                                                                                                                    # Yes
                                                                                                                    if isinstance(obj, basestring):

                                                                                                                    Python3中Unicode和basestring的不再存在(只有str)和字節對象不再是字符串(是整數序列)

                                                                                                                    • 對序列(字符串、列表 、元組), 空序列為false:

                                                                                                                      </li> </ul>

                                                                                                                      # Yes
                                                                                                                      if not seq:
                                                                                                                         pass
                                                                                                                      if seq:
                                                                                                                         pass

                                                                                                                       No

                                                                                                                      if len(seq):    pass if not len(seq):    pass</pre>

                                                                                                                      • 字符串后面不要有大量拖尾空格。

                                                                                                                        </li> </ul>

                                                                                                                        • 不要用 == 進行布爾比較

                                                                                                                          </li> </ul>

                                                                                                                          # Yes
                                                                                                                          if greeting::
                                                                                                                             pass

                                                                                                                           No

                                                                                                                          if greeting == True    pass if greeting is True: # Worse    pass</pre>

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!