如何用PEP 8編寫優雅的Python代碼

目錄以下:python

PEP 8有時候讀做PEP8 或者PEP-8,是一份提供如何編寫Python代碼指南和最佳實踐的文檔,由Guido van Rossum, Barry Warsaw, Nick Coghlan在2001年完成。PEP 8主要注重於提升 Python 代碼的可讀性和一致性。express

PEP全稱爲:Python Enhancement Proposal,一個PEP是一份文檔,它描述了爲Python提出的新特性以及爲社區編寫的Python方面的文檔,好比設計和風格。編程

本教程概述了PEP 8中列出的關鍵指南,它的目標讀者是初級到中級程序員,所以我沒有涉及一些最高級的主題。不過你能夠經過閱讀完整的PEP 8 — Style Guide for Python Code | Python.org文檔來學習高級主題。編程語言

在本教程結束時,你將可以:編輯器

  • 編寫聽從PEP 8規範的代碼
  • 理解PEP 8中列出的指導原則背後的緣由
  • 設置你的開發環境,以便開始編寫符合PEP 8標準的Python代碼

Why We Need PEP 8

可讀性很重要

PEP 8規範存在的目的在於提升Python代碼的可讀性,但爲何可讀性如此重要?爲何編寫具備可讀性的代碼是Python語言的指導原則之一?

正如Guido van Rossum所說:」代碼閱讀的頻率遠遠高於編寫的頻率「。你可能花費幾分鐘或一成天時間編寫一段代碼來處理用戶身份驗證,一旦你寫完它,你就不再會重寫一次,可是你確定會再讀一次,這段代碼可能仍然是你正在進行的項目的一部分。每次你回到那個代碼文件,你必需要記住那部分代碼是作什麼的以及你爲何要寫它,因此可讀性很重要。

若是你是Python新手,在你編寫代碼以後的幾天或幾周內還要你記住代碼片斷的含義可能有點困難。若是你遵循PEP 8標準,你能夠很肯定你對你的變量命名得很好,你會知道你添加了足夠的空格,所以更容易遵循代碼中的邏輯步驟,你還能夠對你的代碼進行很好的註釋,全部的這些都意味着你的代碼具備更高的可讀性,也更容易再次閱讀。做爲初學者,遵循PEP 8的規則可使學習Python成爲更愉快的任務。

若是你正在找工做,那麼遵循PEP 8標準尤其重要,編寫清晰可讀性高的代碼更會突出你的專業性,這將會側面告訴你的老闆,你瞭解怎麼很好地構建你的代碼。

若是你擁有不少編寫Python代碼的經驗,而後你可能須要和其餘人協做開發,編寫可讀性高的代碼在這裏相當重要,其餘人可能此前從未看過你這樣風格的代碼,他必須從新閱讀且理解你的代碼風格,若是擁有你遵循和承認的指南將使其餘人更容易閱讀你的代碼。

Naming Conventions

明瞭勝於晦澀

當你編寫Python代碼的時候,你必須對不少東西命名:變量、函數、類、包等等,選擇合理的名字將爲你節省時間和精力。你將可以從名稱中找出某個變量,函數或類所表明的含義。你還要避免使用不恰當的名稱,由於這樣可能會致使難以調試的錯誤。

::Note: 永遠不要使用 i,o,或 I 單字母名稱,由於這些名稱可能會被誤認爲1和0,具體取決於字體:::

# 這可能看起來像你試圖將2從新分配給零
0 = 2

Naming Styles

下表概述了Python代碼中的一些常見命名風格以及什麼時候應該使用它們:

這些是一些常見的命名約定以及如何使用它們的示例,可是爲了編寫高可讀性代碼,你仍然須要謹慎選擇字母和單詞。除了在代碼中選擇正確的命名風格外,還必須仔細選擇名稱,如下是有關如何儘量有效地執行此操做的一些指示。

How to Choose Names

爲變量、函數、類等選擇名稱是一項挑戰,在編寫代碼時,你應該在命名選擇中加入至關多的思考,由於這樣可使代碼更具可讀性。在Python中爲對象命名的最佳方法是使用描述性名稱來清楚代表對象所表明的內容。

對變量進行命名時,你可能會選擇簡單的單字母小寫名稱,例如x。可是,除非你使用x做爲數學函數的參數,不然並不清楚x表明什麼。想象下你正在將一我的的名字保存爲字符串,而且你但願使用字符串切片來格式化其名稱。你最終會獲得這樣的東西:

# Not recommended
x = 'John Smith'
y, z = x.split()
print(z, y, sep=', ')
# 'Smith, John'

上面代碼能夠很好的運行,可是你必須追蹤x,y,z表示的含義,這樣也會讓你的代碼協做者產生困擾,更明確的名稱選擇將是這樣的:

# Recommended
name = 'John Smith'
first_name, last_name = name.split()
print(last_name, first_name, sep=', ')
# 'Smith, John'

一樣,爲了減小輸入的數量,在選擇名稱時使用單詞縮寫也是頗有誘惑力的,在下面的例子中,我定義了一個函數db(),它接受一個參數x並將其加倍返回:

# Not recommended
def db(x):
    return x * 2

乍一看,這彷佛是一個明智的選擇。 db()很容易當作是double的縮寫,但想象一下,幾天後再看這段代碼,你可能已經忘記了你試圖經過這個函數實現的目標是什麼,這將使猜想它本來的含義變得困難。

下面的例子就比較清晰,若是你幾天後再看這段代碼,你仍然能夠閱讀並理解此函數的目標:

# Recommended
def multiply_by_two(x):
    return x * 2

一樣的理念適用於Python中的全部其餘數據類型和對象,儘可能一直使用最簡潔且最具描述性的名稱。

Code Layout

優美勝於醜陋

如何對代碼佈局對於提高它的可讀性有很大的做用。在本節中,你將學習如何添加垂直空格以提升代碼的可讀性。你還將學習如何處理PEP 8中建議的79字符行限制。

Blank Lines

垂直空格或空行能夠極大地提升代碼的可讀性,彙集在一塊兒的代碼多是壓倒性的且難以閱讀,一樣,代碼中的空行太多會使其看起來很是稀疏,讀者可能須要進行不必的滾動,如下是關於如何使用垂直空白的三個關鍵指南。

用兩個空行包圍頂級函數和類,頂級函數和類應該是徹底自包含的,並處理單獨的功能,在它們周圍放置額外的垂直空間是有意義的,所以很明顯它們是分開的:

class MyFirstClass:
    pass


class MySecondClass:
    pass


def top_level_function():
    return None

用一個空行包圍類中的方法定義,在一個類中,函數都彼此有聯繫,最好只在它們之間留一行:

class MyClass:
    def first_method(self):
        return None

    def second_method(self):
        return None

在函數內部謹慎地使用空行,以顯示清晰的步驟,有時候一個複雜的函數必須在return語句以前完成好幾個步驟,爲了幫助閱讀者理解函數裏面的邏輯,在每一個步驟之間留一個空行會頗有幫助。

在下面的示例中,有一個計算列表方差的函數,這個問題能夠分爲兩個步驟,因此我在每一個步驟之間留下了一個空行,在return語句以前還有一個空行。這有助於讀者清楚地看到返回的內容:

def calculate_variance(number_list):
    sum_list = 0
    for number in number_list:
        sum_list = sum_list + number
    mean = sum_list / len(number_list)

    sum_squares = 0
    for number in number_list:
        sum_squares = sum_squares + number**2
    mean_squares = sum_squares / len(number_list)

    return mean_squares - mean**2

若是仔細地使用垂直空格,能夠大大提升代碼的可讀性,它有助於讀者直觀地理解你的代碼如何分紅幾個部分,以及這些部分如何相互關聯。

Maximum Line Length and Line Breaking

PEP 8建議每行代碼限制在79個字符之內,這是由於它容許多個文件並排打開,同時也避免了換行,固然,將語句保持在79個字符之內並不老是可行的。PEP 8概述了容許語句在多行上運行的方法。

若是代碼包含在括號、方括號或大括號中,Python將會認爲代碼是一行的:

def function(arg_one, arg_two,
             arg_three, arg_four):
    return arg_one

若是不能用上述的方式進行每行代碼延續,那麼可使用反斜槓代替換行:

from mypkg import example1, \
    example2, example3

可是,若是可使用第一個方案,那麼就應該儘可能這樣作。

若是須要在二元運算符周圍作換行操做,例如+*,那麼須要將換行操做放在前面,這條規則源於數學,數學家贊成在二元運算符以前換行以可提升可讀性,比較如下兩個例子。

下面是在二元運算符以前換行的示例:

# Recommended
total = (first_variable
         + second_variable
         - third_variable)

你能夠立刻反應過來哪些變量正在相加後者相減,由於操做符緊鄰着變量。

如今,讓咱們看一個在二元運算符以後換行的示例:

# Not Recommended
total = (first_variable +
         second_variable -
         third_variable)

在這裏,很難看出哪一個變量被加,哪一個變量被減。

在二元運算符以前換行可讓代碼更加具備可讀性,所PEP 8鼓勵這種方式。在二元運算符以後換行的代碼仍然符合PEP 8,可是,咱們鼓勵你在二元運算符以前換行。

Indentation

當存在多種可能,不要嘗試去猜想
而是儘可能找一種,最好是惟一一種明顯的解決方案(若是不肯定,就用窮舉法)

縮進,即前導空格,在Python中很是重要。Python中代碼行的縮進級別決定了語句如何組合在一塊兒。

思考下面的例子:

x = 3
if x > 5:
    print('x is larger than 5')

縮進的print語句使得Python明白只有if語句返回True才能繼續執行它,一樣的縮進適用於告訴 Python 在調用函數時要執行哪些代碼,或者哪些代碼屬於給定的類。

PEP 8制定的關鍵縮進規則以下:

  • 使用4個連續的空格來表示縮進。
  • 選擇空格而不是製表符(Tab)。

Tabs vs. Spaces

如同上述所說,當你進行縮進的時候,你最好用空格代替製表符,你能夠直接對文本編輯器的設置進行調整,當你按Tab的時候轉換爲4個空格的輸出

若是你使用的是Python 2而且混合使用了製表符和空格來縮進代碼,當你運行的時候可能不會看見錯誤。爲了幫助你檢查一致性,能夠在從命令行運行Python 2代碼時添加-t標誌。當你不一致地使用製表符和空格時,解釋器將會發出警告:

python2 -t code.py
code.py: inconsistent use of tabs and spaces in indentation

相反,若是你使用-tt標誌,解釋器將發出錯誤而不是警告,使用此方法的好處是解釋器會告訴你縮進不一致的位置在哪裏:

python2 -tt code.py
File "code.py", line 3
    print(i, j)
             ^
TabError: inconsistent use of tabs and spaces in indentation

Python 3不容許製表符和空格混合使用,所以,若是你使用的是Python3,解釋器將會自動報錯:

python3 code.py
File "code.py", line 3
    print(i, j)
              ^
TabError: inconsistent use of tabs and spaces in indentation

你能夠在編寫Python代碼中使用製表符或空格來表示縮進,可是,若是你使用的是Python 3,則必須與你的選擇保持一致,不然你的代碼將不能運行。PEP 8推薦你老是使用4個連續的空格來表示縮進。

Indentation Following Line Breaks

當你爲了保證每行在79個字符如下而進行換行時,使用縮進來提升代碼可讀性是頗有用的,它容許讀者區分兩行代碼和跨越兩行的單行代碼,這裏有兩種縮進風格供你選擇。

第一個是將縮進塊與開始的分隔符對齊:

def function(arg_one, arg_two,
             arg_three, arg_four):
    return arg_one

有時你會發現只須要4個空格就能夠與開口分隔符對齊,這種狀況常常發生在 if 語句中,若是跨多行的if+ +(構成4個字符,那麼就會發生這種狀況,在這種狀況下,很難肯定 if 語句中嵌套的代碼塊從哪裏開始:

x = 5
if (x > 3 and
    x < 10):
    print(x)

在這種狀況下,PEP 8提供了兩種替代方案來幫助你提升代碼可讀性:

  • 在最後的條件後添加註釋,因爲大多數編輯器中有語法高亮顯示,這能夠將條件與嵌套代碼分開:
x = 5
if (x > 3 and
    x < 10):
    # Both conditions satisfied
    print(x)
  • 在換行中添加額外的縮進:
x = 5
if (x > 3 and
        x < 10):
    print(x)

換行符後的另外一種縮進方式是懸掛縮進(hanging indent),這是一個印刷術語,意思是段落或語句中除第一行之外的每一行都縮進,可使用懸掛縮進直觀地表示一行代碼的延續。下面是一個例子:

var = function(
    arg_one, arg_two,
    arg_three, arg_four)

::Note:當你正在使用hanging indent時,第一行不得有任何參數。如下示例不符合PEP 8::

# Not Recommended
var = function(arg_one, arg_two,
    arg_three, arg_four)

使用hanging indent時,能夠添加額外的縮進以區分連續行與函數內包含的代碼。下面是一個難以閱讀的例子,由於函數裏面的代碼和連續行的縮進等級是相同的:

# Not Recommended
def function(
    arg_one, arg_two,
    arg_three, arg_four):
    return arg_one

相反,最好在一行代碼換行後使用雙縮進,這有助於你區分函數參數和函數內部構造,從而提升可讀性:

def function(
        arg_one, arg_two,
        arg_three, arg_four):
    return arg_one

當你編寫遵循PEP 8規範代碼的時候,每行字符在79以內的規則使你必須強制換行,爲了提升可讀性,你應該縮進一行,以代表它是一個連續的行。作到這一點有兩種方法,第一種是將縮進的塊與開始的分隔符對齊,第二種是使用懸掛縮進,在換行以後,你能夠自由選擇使用哪一種方法進行縮進。

Where to Put the Closing Brace

一行代碼的換行操做容許你在括號、方括號或大括號後面斷開一行,這會形成一個問題,就是很容易忘記關閉括號,但重要的是要把它放在合理的地方,不然,它會使讀者感到困惑,Pep 8爲隱含的行延續中的結束括號的位置提供了兩個選項:

  • 使用前一行的第一個非空白字符排列右括號:
list_of_numbers = [
    1, 2, 3,
    4, 5, 6,
    7, 8, 9
    ]
  • 將結束括號與聲明行的第一個字符對齊:
list_of_numbers = [
    1, 2, 3,
    4, 5, 6,
    7, 8, 9
]

你能夠自由地選擇任何一種方式,可是,和以前說的同樣,一致性是關鍵,因此以後的代碼就要堅持使用你選擇的某一個方案以保持代碼一致性。

Comments

若是你沒法向人描述你的方案,那確定不是一個好方案;反之亦然

你應該使用註釋來講明編寫的代碼,這對記錄你的代碼很是重要,這樣你的任何協做者均可以理解它。當你或者其餘人閱讀代碼註釋,他們應該可以很容易地理解註釋所應用的代碼,以及它如何與代碼的其他部分相匹配。

下面是一些你爲你代碼做註釋時候須要注意的關鍵點:

  • 將註釋和文檔字符串的行長限制爲72個字符
  • 使用完整的句子,以大寫字母開頭
  • 註釋隨着代碼的更新而更新

Block Comments

使用塊註釋來記錄一小部分代碼,當你必須編寫幾行代碼來執行單個操做時,它們很是有用,例如從文件導入數據或更新數據庫記錄。其重要性在於它們能夠幫助其餘人理解給定代碼塊的用途和功能。

PEP 8提供如下規則來編寫註釋:

  • 將塊註釋縮進到其描述代碼的相同級別
  • 用#加上一個空格開始每一行的註釋
  • 用包含單個#的行分隔段落

這是一個解釋for循環功能的塊註釋,請注意,句子爲了每行保留79個字符行限制進行了換行:

for i in range(0, 10):
    # Loop over i ten times and print out the value of i, followed by a
    # new line character
    print(i, '\n')

有時,若是代碼技術性較強,那麼有必要在塊註釋中使用多個段落:

def quadratic(a, b, c, x):
    # Calculate the solution to a quadratic equation using the quadratic
    # formula.
    #
    # There are always two solutions to a quadratic equation, x_1 and x_2.
    x_1 = (- b+(b**2-4*a*c)**(1/2)) / (2*a)
    x_2 = (- b-(b**2-4*a*c)**(1/2)) / (2*a)
    return x_1, x_2

若是你不肯定什麼樣的註釋類型是合適的,那麼塊註釋一般是正確的選擇。請儘可能在你的代碼中添加註釋,一旦你對代碼進行了更新也請務必對註釋進行更新!

Inline Comments

行內註釋對單個語句中的一段代碼進行了解釋,這有助於提醒你或者其餘人爲何某行代碼是必須的,如下是 PEP 8對他們的評價:

  • 謹慎使用行內註釋
  • 在與它們引用的語句相同的行上寫入行內註釋
  • 從語句中用兩個或多個空格分隔行內註釋
  • 像塊註釋那樣,用#加上一個空格開始每一行的註釋
  • 不要用它們來解釋明顯的問題

下面是一個行內註釋的例子:

x = 5  # This is an inline comment

有時,行內註釋彷佛是必要的,可是你可使用更好的命名約定,下面是一個例子:

x = 'John Smith'  # Student Name

這裏,行內註釋爲變量提供了額外的說明信息,然而用x做爲一我的名的變量名不是很好的作法,若是你對變量重命名,是能夠不用使用行內註釋的:

student_name = 'John Smith'

最後,像這樣的行內註釋是很差的作法,由於它們陳述了顯而易見且雜亂的代碼:

empty_list = []  # Initialize empty list

x = 5
x = x * 5  # Multiply x by 5

行內註釋比塊註釋更具體,而且容易在非必要時候添加它們,這會致使代碼混亂。除非你肯定須要行內註釋,否則使用塊註釋避免代碼混亂的問題比較好,堅持使用塊註釋,可讓你的代碼更加符合PEP8的標準。

Documentation Strings

Documentation strings 或者說docstrings, 是用雙引號(」」」)或單引號(’’’)括起來的字符串,它們出如今任何函數,類,方法或模塊的第一行,你可使用它們來解釋和記錄特定的代碼塊。這裏有一個對應的PEP,見PEP 257,但你能夠從本節閱讀總結的經驗:

使用文檔字符串的重要規則以下:

  • 文檔字符串兩邊都有三個雙引號環繞,好比:"""This is a docstring"""
  • 爲全部公共模塊,函數,類和方法編寫docstrings
  • 使用單行"""結束多行docstring
def quadratic(a, b, c, x):
    """Solve quadratic equation via the quadratic formula.

    A quadratic equation has the following form:
    ax**2 + bx + c = 0

    There always two solutions to a quadratic equation: x_1 & x_2.
    """
    x_1 = (- b+(b**2-4*a*c)**(1/2)) / (2*a)
    x_2 = (- b-(b**2-4*a*c)**(1/2)) / (2*a)

    return x_1, x_2
  • 對於單行docstrings,保持"""在同一行:
def quadratic(a, b, c, x):
    """Use the quadratic formula"""
    x_1 = (- b+(b**2-4*a*c)**(1/2)) / (2*a)
    x_2 = (- b-(b**2-4*a*c)**(1/2)) / (2*a)

    return x_1, x_2

想要了解更多,請閱讀Documenting Python Code: A Complete Guide – Real Python

Whitespace in Expressions and Statements

間隔勝於緊湊

正確使用空格在表達式和語句中很是有用,若是代碼中沒有足夠的空格,那麼代碼應該很難閱讀,由於他們都湊在一塊兒,若是空格太多,又會難以在視覺上將完整的語句聯繫出來。

Whitespace Around Binary Operators

在進行如下二元操做的時候,應該在其兩邊加上空格:

  • 分配操做(=, +=, -=, 等等)
  • 比較(==, !=, >, <. >=, <=)和 (is, is not, in, not in)
  • 布爾(and, not, or)

::Note:當=是爲一個函數的參數賦值時候就不用在兩邊加空格::

# Recommended
def function(default_parameter=5):
    # ...


# Not recommended
def function(default_parameter = 5):
    # ...

若是語句中有多個運算符,則在每一個運算符先後添加單個空格可能會讓人感到困惑,相反,最好只在優先級最低的運算符周圍添加空格,尤爲是在執行數學運算時。如下是幾個例子:

# Recommended
y = x**2 + 5
z = (x+y) * (x-y)

# Not Recommended
y = x ** 2 + 5
z = (x + y) * (x - y)

還能夠將此應用於有多個條件的if語句:

# Not recommended
if x > 5 and x % 2 == 0:
    print('x is larger than 5 and divisible by 2!')

在上面的示例中,and操做具備最低優先級,所以,能夠下面這樣更清楚地表達if語句:

# Recommended
if x>5 and x%2==0:
    print('x is larger than 5 and divisible by 2!')

你能夠自由選擇哪一個方式更清晰,但須要注意的是你必須在運算符的任何一側使用相同數量的空格。

下面的例子是不被容許的:

# Definitely do not do this!
if x >5 and x% 2== 0:
    print('x is larger than 5 and divisible by 2!')

在切片中,冒號做爲二元運算符。所以,上一節中概述的規則也適用於此,而且其任何一方都應該有相同數量的空白,如下列表切片示例是合法的:

list[3:4]

# Treat the colon as the operator with lowest priority
list[x+1 : x+2]

# In an extended slice, both colons must be
# surrounded by the same amount of whitespace
list[3:4:5]
list[x+1 : x+2 : x+3]

# The space is omitted if a slice parameter is omitted
list[x+1 : x+2 :]

總之,你應該使用空格包圍大多數運算符,可是,此規則有一些注意事項,例如在函數參數中或在一個語句中組合多個運算符時。

When to Avoid Adding Whitespace

在某些狀況下,添加空格可能會使代碼難以閱讀,太多的空格會使代碼過於稀疏而難以理解。 PEP 8概述了一些很是明顯的例子應當不使用空格

在一行的末尾避免添加空格是最重要的地方,這稱爲trailing whitespace,它是不可見的,可能產生難以追蹤的錯誤。

如下列表概述了一些應避免添加空格的狀況:

  • 直接放在括號、方括號或大括號內:
# Recommended
my_list = [1, 2, 3]

# Not recommended
my_list = [ 1, 2, 3, ]
  • 在逗號,分號或冒號以前:
x = 5
y = 6

# Recommended
print(x, y)

# Not recommended
print(x , y)
  • 在打開函數調用的參數列表的開括號以前:
def double(x):
    return x * 2

# Recommended
double(3)

# Not recommended
double (3)
  • 在開始索引或切片的開括號以前:
# Recommended
list[3]

# Not recommended
list [3]
  • 在尾隨逗號和右括號之間:
# Recommended
tuple = (1,)

# Not recommended
tuple = (1, )
  • 對齊賦值運算符:
# Recommended
var1 = 5
var2 = 6
some_long_var = 7

# Not recommended
var1          = 5
var2          = 6
some_long_var = 7

確保你的代碼中沒有尾隨空格。 在其餘狀況下,PEP 8不鼓勵添加額外的空格,例如立直接放在括號、方括號或大括號內,以及逗號和冒號以前。 爲了對齊操做符,也不該該添加額外的空格。

Programming Recommendations

簡潔勝於複雜

你常常會發現有幾種方法能夠在 Python (以及任何其餘編程語言)中執行相似的操做。在本節中,你將看到PEP 8提供的一些建議用來消除這種歧義而且保持一致性。

不要使用等價運算符將布爾值與True或False進行比較,你常常須要檢查布爾值是True仍是False,當這樣操做時,請使用以下所示的語句直觀地執行此操做:

# Not recommended
my_bool = 6 > 5
if my_bool == True:
    return '6 is bigger than 5'

這裏不須要使用等價運算符==, bool只能取值True或False,按照下面這樣寫就好了:

# Recommended
if my_bool:
    return '6 is bigger than 5'

這種在if語句中使用bool的方式能夠寫更少的代碼而且更加簡單,所以PEP 8鼓勵使用這種方式。

在if語句中判斷列表是否爲空,當你但願肯定列表是否爲空時,你一般會判斷列表的長度,若是列表爲空,那麼長度爲0,在if語句中使用時等於False,這裏有一個例子:

# Not recommended
my_list = []
if not len(my_list):
    print('List is empty!')

可是,在Python中,任何空列表,字符串或元組均可以當爲False的。所以,咱們能夠提出一個更簡單的替代方案:

# Recommended
my_list = []
if not my_list:
    print('List is empty!')

兩種方法均可以判斷列表是否爲空,可是第二種方式更加簡潔,所以PEP 8鼓勵使用這種方式。

在if語句中,使用 is not 比 no ... is in 好,當你須要肯定一個變量是否被賦值,這裏有兩種方法,第一種是評估if語句中的x是否是爲非None,以下所示:

# Recommended
if x is not None:
    return 'x exists!'

第二種方案是如今if語句中判斷x是否是None,再進行not操做:

# Not recommended
if not x is None:
    return 'x exists!'

兩種方法均可以判斷x是否爲None,可是第一種方式更加簡單,所以PEP 8鼓勵使用這種方式。

當你想表達if x is not None時,不要使用if x,有時候,你可能擁有一個函數帶有默認值爲None的參數,當對參數arg檢查是否帶有不一樣的值的時候常常會犯下面這樣的錯誤:

# Not Recommended
if arg:
    # Do something with arg...

此代碼檢查的是arg是否爲真,但相對的你要的是檢查是否爲None,因此下面這樣寫比較好:

# Recommended
if arg is not None:
    # Do something with arg...

上面的錯誤會使得判斷是否爲真和not None相等,你能夠設置arg = [],如上所述,空列表在Python中被認爲是False,所以,儘管參數被聲明爲[],但條件並無知足,所以函數裏面的代碼if聲明並不能被執行。

用.startswith() 和.endswith()代替切片,若是你想檢查一段字符串的前綴或者後綴是否帶有字符串cat,這看起來使用列表切片彷佛比較明智,可是,列表切片容易出錯,您必須對前綴或後綴中的字符數進行硬編碼,對於那些不太熟悉Python列表切片的人來講很難看清楚你想要實現的目的:

# Not recommended
if word[:3] == 'cat':
    print('The word starts with "cat"')

然而,仍是使用.startswith():可讀性比較高:

# Recommended
if word.startswith('cat'):
    print('The word starts with "cat"')

一樣的,當你想檢查字符串後綴也是一樣的原理,下面的示例概述瞭如何檢查字符串是否以jpg結尾:

# Not recommended
if file_name[-3:] == 'jpg':
    print('The file is a JPEG')

雖然結果是正確的,可是符號有點複雜且難以閱讀,與之相對的,你能夠用.endswith()實現,看下面例子:

# Recommended
if file_name.endswith('jpg'):
    print('The file is a JPEG')

就像上面的列出的編程建議,咱們目標是編寫清晰以及可讀性較高的代碼,在Python中,有許多不一樣的方法能夠實現相同的結果,所以有關選擇哪一種方法的指南頗有幫助。

When to Ignore PEP 8

何時忽略PEP 8?對於這個問題有個簡短的答案,那就是永遠不會

若是你嚴格遵循 PEP 8,就能夠保證您擁有乾淨、專業和可讀的代碼。 這對你以及合做者和潛在僱主都有好處。

可是,PEP 8中的一些指導方針在如下實例中不適用:

  • 若是遵照PEP 8將破壞與現有軟件的兼容性
  • 若是你正在從事的工做的代碼與 PEP 8不一致
  • 若是代碼須要與舊版本的Python版本保持兼容

Tips and Tricks to Help Ensure Your Code Follows PEP 8

想要你的代碼兼容PEP 8,那你得記住很多規範,在開發代碼時,記住全部這些規則多是一項艱鉅的任務。特別是對老項目進行更新以兼容PEP 8時,幸運的是,有些工具能夠幫助你加快這一過程,這裏有兩個工具能夠幫你強制兼容PEP 8規範:lintersautoformatters

Linters

Linters是分析代碼和標記錯誤的程序,他們能夠爲你如何修復錯誤提供建議,在做爲文本編輯器的擴展安裝時,Linters特別有用,由於它們標記了你編程時的錯誤和格式問題。在本節中,您將看到Linters程序是如何工做的大綱,最後還有文本編輯器擴展的連接。

對於Python代碼,最好的linters以下:

  • pycodestyle)是一個根據PEP 8中的某些風格約定來檢查Python代碼的工具
# 使用pip安裝pycodestyle
pip install pycodestyle

使用如下命令在終端中使用pycodestyle

pycodestyle code.py
code.py:1:17: E231 missing whitespace after ','
code.py:2:21: E231 missing whitespace after ','
code.py:6:19: E711 comparison to None should be 'if cond is None:'
  • flake8是一個結合了調試器,pyflakespycodestyle的工具
# 使用pip安裝flake8
pip install flake8

使用如下命令在終端中使用pycodestyle

flake8 code.py
code.py:1:17: E231 missing whitespace after ','
code.py:2:21: E231 missing whitespace after ','
code.py:3:17: E999 SyntaxError: invalid syntax
code.py:6:19: E711 comparison to None should be 'if cond is None:'

還顯示了輸出的示例。

::Note:額外輸出的一行表示語法錯誤。::

這些也可用做Atom,Sublime Text,Visual Studio Code和VIM的擴展。您還能夠找到有關爲Python開發設置Sublime Text和VIM的指南,以及Real Python中一些流行的文本編輯器的概述。

Autoformatters

Autoformatters能夠重構你的代碼以使其符合PEP 8規範,像black程序就能夠根據PEP 8規範從新格式化你的代碼,一個很大的區別是它將行長度限制爲88個字符,而不是79個字符。可是,您能夠經過添加命令行標誌來覆蓋它,以下面的示例所示。

可使用pip安裝black,它須要Python 3.6+

pip install black

它能夠經過命令行運行,就像Linters同樣。假設你從名爲code.py裏面不符合PEP 8規範的代碼開始:

for i in range(0,3):
    for j in range(0,3):
        if (i==2):
            print(i,j)

你能夠在命令行中運行以下代碼:

black code.py
reformatted code.py
All done!

code.py將會被從新格式化爲以下所示:

for i in range(0, 3):
    for j in range(0, 3):
        if i == 2:
            print(i, j)

若是你想要更改行長度限制,則可使用—line-length標誌:

black --line-length=79 code.py
reformatted code.py
All done!

另外兩個autoformatters 分別爲autopep8yapf,它們和black操做相似。

另外一個Real Python教程,由 Alexander van Tol編寫的Python Code Quality: Tools & Best Practices詳細解釋瞭如何使用這些工具。

Conclusion

你如今已經知道如何使用PEP 8中的指南編寫高質量,可讀高的Python代碼,雖然指南看起來很迂腐,但遵循它們能夠真正改善你的代碼,特別是在與潛在僱主或合做者共享代碼時。

在本教程中你瞭解到:

  • 什麼是 PEP 8以及其存在的緣由
  • 爲何你應該編寫符合PEP 8標準的代碼
  • 如何編寫符合PEP 8的代碼

除此以外,您還了解了如何使用linters和autoformatters根據PEP 8指南檢查代碼。

若是你想了解更多,能夠閱讀full documentation)或者瀏覽pep8.org,這些教程不只提供了相似的信息同時也提供了很好的格式讓你閱讀,在這些文檔中,您將找到本教程未涉及的其他PEP 8指南。

相關文章
相關標籤/搜索