1. 程式人生 > 其它 >第14天 static關鍵字詳解\抽象類和介面

第14天 static關鍵字詳解\抽象類和介面

3. 程式碼佈局http://pythoncode.baoshu.red/PythonCodingStyle/2-1.%E8%A7%84%E8%8C%83%E4%BF%AE%E7%82%BC-PEP8%E8%A7%84%E8%8C%83%E8%A7%A3%E8%AF%BB.html

3.PEP8解讀

python官網PEP8文件地址:https://www.python.org/dev/peps/pep-0008/

1. 什麼是PEP?

PEP是 Python Enhancement Proposal 的縮寫,翻譯過來就是 Python增強建議書 。

PEP8譯者:本文基於 2013-08-02 最後修改的 PEP8 版本翻譯,若要檢視英文原文,請參考PEP8

然而,有時候編碼規範的建議並不適用。

許多專案都有一套專有的編碼風格指南,當衝突發生時,應以專案編碼規範為優先。

特別是不要為了遵守PEP約定而破壞相容性!

當以下情況發生時,也是忽略某個風格指南的好理由:

  1. 當遵守規範會降低程式碼可讀性,甚至對於那些依循 PEP 去閱讀程式碼的人也是這樣時。

  2. 當遵守規範會與其他部分的程式碼風格背離時 — 當然也許這是一個修正某些混亂程式碼的機會。

  3. 當那些並沒有遵循規範的舊程式碼已無法修改時,而且也沒有充足的理由去修改他們。

  4. 當你的程式碼需要與舊版本的 Python 保持相容,而舊版本的 Python 不支援規範中提到的特性時。

2.PEP8的主要內容

  1. 程式碼佈局

  2. 字串引號

  3. 表示式與空格

  4. 註釋的使用

  5. 文件描述

  6. 命名規範

  7. 編碼建議

3. 程式碼佈局

1. 縮排

  • 每一級縮排使用4個空格。

  • 續行應該與其包裹元素對齊,要麼使用圓括號、方括號和花括號內的隱式行連線來垂直對齊,

​ 要麼使用掛行縮排對齊

  • 當使用掛行縮排時,應該考慮到第一行不應該有引數,以及使用縮排以區分自己是續行。

不推薦:

# 沒有使用垂直對齊時,禁止把引數放在第一行
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)

# 用更多的縮排來與其他行區分
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)
  • 掛行縮排不一定要用4個空格

# 掛行縮排不一定要用4個空格
foo = long_function_name(
  var_one, var_two,
  var_three, var_four)
  • 當if語句的條件部分長到需要換行寫的時候,注意可以在兩個字元關鍵字的連線處(比如if),增加一個空格,再增加一個左括號來創造一個4空格縮排的多行條件。這會與if語句內同樣使用4空格縮排的程式碼產生視覺衝突。對於如何(或是否)在視覺上進一步將這些條件行與if語句內的巢狀套件區分開,PEP不做任何明確的表述。可使用的選項包括但不限於下面幾種情況:

# 沒有額外的縮排
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()

# 在條件判斷的語句新增額外的縮排
if (this_is_one_thing
        and that_is_another_thing):
    do_something()
  • 在多行結構中的大括號/中括號/小括號的右括號可以與內容對齊單獨起一行作為最後一行的第一個字元,

# 就像這樣:
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',
)

2. 製表符還是空格?

空格是首選的縮排方式。 製表符只能用於與同樣使用製表符縮排的程式碼保持一致。 Python3不允許同時使用空格和製表符的縮排。

3. 行的最大長度

  1. 所有行限制的最大字元數為79。

  2. 沒有結構化限制的大塊文字(文件字元或者註釋),每行的最大字元數限制在72。

4. 在二元運算子之前應該換行嗎?

幾十年來,推薦的風格是在二元運算子之後中斷。但是這回影響可讀性,原因有二:操作符一般分佈在螢幕上不同的列中,而且每個運算子被移到了運算元的上一行。

下面例子這個情況就需要額外注意,那些變數是相加的,那些變數是相減的:

# 不推薦: 操作符離運算元太遠
income = (gross_wages +
          taxable_interest +
          (dividends - qualified_dividends) -
          ira_deduction -
          student_loan_interest)

為了解決這種可讀性的問題,數學家和他們的出版商遵循了相反的約定。

遵循數學的傳統能產出更多可讀性高的程式碼:

# 推薦:運算子和運算元很容易進行匹配
income = (gross_wages
          + taxable_interest
          + (dividends - qualified_dividends)
          - ira_deduction
          - student_loan_interest)

5. 空行

  1. 頂層函式和類的定義,前後用兩個空行隔開。

  2. 類裡的方法定義用一個空行隔開。

  3. 相關的功能組可以用額外的空行(謹慎使用)隔開。

  4. 一堆相關的單行程式碼之間的空白行可以省略。

  5. 在函式中使用空行來區分邏輯段(謹慎使用)。

6. 原始檔編碼

  • Python核心釋出版本中的程式碼總是以UTF-8格式編碼(或者在Python2中用ASCII編碼)。

  • 使用ASCII(在Python2中)或UTF-8(在Python3中)編碼的檔案不應具有編碼宣告。

  • 對於Python 3和更高版本,標準庫規定了以下策略(參見 PEP 3131):

    • Python標準庫中的所有識別符號必須使用ASCII識別符號,並在可行的情況下使用英語單詞(在許多情況下,縮寫和技術術語是非英語的)。

    • 此外,字串文字和註釋也必須是ASCII。

7. Imports 匯入

  1. 匯入通常在分開的行,例如:

    # 推薦: 
    import os
    import sys
    
    # 不推薦:  
    import sys, os
    
    # 也可以:
    from subprocess import Popen, PIPE
    
  2. 匯入總是位於檔案的頂部,在模組註釋和文件字串之後,在模組的全域性變數與常量之前。

  3. 匯入應該按照以下順序分組:

    1. 標準庫匯入
       2. 相關第三方庫匯入
       3. 本地應用/庫特定匯入
       4. 你應該在每一組匯入之間加入空行
    
  4. 推薦使用絕對路徑匯入,如果匯入系統沒有正確的配置(比如包裡的一個目錄在sys.path裡的路徑後),使用絕對路徑會更加可讀並且效能更好(至少能提供更好的錯誤資訊):

    import mypkg.sibling
    from mypkg import sibling
    from mypkg.sibling import example
    
  5. 當從一個包含類的模組中匯入類時,常常這麼寫:

    from myclass import MyClass
    from foo.bar.yourclass import YourClass
    
  6. 如果上述的寫法導致名字的衝突,那麼這麼寫:

    import myclass
    import foo.bar.yourclass
    

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

  7. 避免萬用字元的匯入(from import *),因為這樣做會不知道名稱空間中存在哪些名字,會使得讀取介面和許多自動化工具之間產生混淆。

8.模組級Dunder名稱

模組級“dunders”(也就是名字裡有兩個字首下劃線和兩個字尾下劃線)

__all____author____version__等應被放置在模組文件字串之後,以及除from__future__之外的import表示式前面。Python要求將來在模組中的匯入,必須出現在除文件字串之外的其他程式碼之前。

"""This is the example module.

This module does stuff.
"""

from __future__ import barry_as_FLUFL

__all__ = ['a', 'b', 'c']
__version__ = '0.1'
__author__ = 'Cardinal Biggles'

import os
import sys

4. 字串引號

在Python中,單引號和雙引號字串是相同的。PEP不會為這個給出建議。選擇一條規則並堅持使用下去。當一個字串中包含單引號或者雙引號字元的時候,使用和最外層不同的符號來避免使用反斜槓,從而提高可讀性。

對於三引號字串,總是使用雙引號字元來與PEP 257中的文件字串約定保持一致。

5. 表示式和語句中的空格

總體原則,避免不必要的空格。

  1. 各種右括號前不要加空格。

# 符合約定的程式碼
spam(ham[1], {eggs: 2})

# 不符合約定的程式碼
spam( ham[ 1 ], { eggs: 2 } )
  1. 逗號、冒號、分號前不要加空格。

# 符合約定的程式碼
if x == 4: print x, y; x, y = y, x
  
# 不符合約定的程式碼
if x == 4 : print x , y ; x , y = y , x
  1. 函式的左括號前不要加空格。如Func(1)。

# 符合約定程式碼
spam(1)

# 不符合約定的程式碼
spam (1)
  1. 序列的左括號前不要加空格。如list[2]。

# 符合約定的程式碼
dict['key'] = list[index]

# 不符合約定的程式碼
dict ['key'] = list [index]
  1. 操作符左右各加一個空格,不要為了對齊增加空格。

# 符合約定的程式碼
x = 1
y = 2
long_variable = 3

# 不符合約定的程式碼
x             = 1
y             = 2
long_variable = 3
  1. 函式預設引數使用的賦值符左右省略空格。

# 符合約定的程式碼
def complex(real, imag=0.0):
    return magic(r=real, i=imag)
  
# 不符合約定的程式碼
def complex(real, imag = 0.0):
    return magic(r = real, i = imag)
  1. 不要將多句語句寫在同一行,儘管使用’;’允許。

  2. if/for/while語句中,即使執行語句只有一句,也必須另起一行。

複合語句(同一行中的多個語句)通常是不允許的。

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

# 不推薦:
if foo == 'blah': do_blah_thing()
do_one(); do_two(); do_three()

# 雖然有時候將小的程式碼塊和 if/for/while 放在同一行沒什麼問題,多行語句塊的情況不要這樣用,同樣也要避免程式碼行太長! 
# 不推薦:
if foo == 'blah': do_blah_thing()
for x in lst: total += x
while t < 10: t = delay()

# 不推薦:
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()

6. Comments 註釋

總體原則,錯誤的註釋不如沒有註釋。所以當一段程式碼發生變化時,第一件事就是要修改註釋!註釋必須使用英文,最好是完整的句子,首字母大寫,句後要有結束符,結束符後跟兩個空格,開始下一句。 如果是短語,可以省略結束符。

  1. 塊註釋 在一段程式碼前增加的註釋。在‘#’後加一空格。段落之間以只有‘#’的行間隔。比如:

# Description : Module config.
# 
# Input : None
#
# Output : None
  1. 行註釋 在一句程式碼後加註釋。比如:

x = x + 1           # Increment x

​ 但是這種方式儘量少使用。 3. 避免無謂的註釋。

  1. 文件字串 要為所有的公共模組,函式,類以及方法編寫文件說明。 非公共的方法沒有必要,但是應該有一個描述方法具體作用的註釋。這個註釋應該在def那一行之後。 對於單行的文件說明,尾部的三引號應該和文件在同一行。 特別需要注意的是,多行文件說明使用的結尾三引號應該自成一行,例如:

    """Return a foobang
    Optional plotz says to frobnicate the bizbaz first.
    """
    

7. Naming Conventions 命名規範

總體原則,新編程式碼必須按下面命名風格進行,現有庫的編碼儘量保持風格。

Python庫的命名規範很亂,從來沒能做到完全一致。但是目前有一些推薦的命名標準。

約定俗成的命名約定:

  1. Names to Avoid 應避免的名字

    • 永遠不要使用字母‘l’(小寫的L),‘O’(大寫的O),或者‘I’(大寫的I)作為單字元變數名。

    • 在有些字型裡,這些字元無法和數字0和1區分,如果想用‘l’,用‘L’代替。

  2. Class Names 類名

    • 類名一般使用首字母大寫的約定。

    • 在介面被文件化並且主要被用於呼叫的情況下,可以使用函式的命名風格代替。

    • 注意,對於內建的變數命名有一個單獨的約定:大部分內建變數是單個單詞(或者兩個單詞連線在一起),首字母大寫的命名法只用於異常名或者內部的常量。

  3. Function Names 函式名

    • 函式名應該小寫,如果想提高可讀性可以用下劃線分隔。

    • 大小寫混合僅在為了相容原來主要以大小寫混合風格的情況下使用(比如 threading.py),保持向後相容性。

  4. Function and method arguments 函式和方法引數

    • 始終要將 self 作為例項方法的的第一個引數。

    • 始終要將 cls 作為類靜態方法的第一個引數。

    • 如果函式的引數名和已有的關鍵詞衝突,在最後加單一下劃線比縮寫或隨意拼寫更好。因此 class_ 比 clss 更好。(也許最好用同義詞來避免這種衝突)

總結:

  • 嚴格要求4個空格縮排,而不是製表符

  • 注意程式碼長度,每行不超過79個字元,並適當使用換行符

  • 注意適當的程式碼空行以更好的區分程式碼區域

  • 程式碼註釋和文件註釋說明必須正確,並優先更新

  • 原始碼編碼格式統一使用utf-8,或和舊檔案程式碼保持一致

  • 從檔案到類與函式甚至是變數的命名都要保持規範,且不要使用中文

  • 重要的是要意識到程式碼的閱讀比編寫的頻率要高很多很多