天天看點

Python PEP8 基本常用規範PEP8規範總結

PEP8規範總結

PEP8 是什麼呢,簡單說就是一種編碼規範,是為了讓代碼“更好看”,更容易被閱讀。 具體有這些規範,參考 PEP 8 –Style Guide for Python Code.當然也可以使用Pycharm檢查或使用pylint.下面是規範總結

縮進

  • 不要使用 tab 縮進
  • 使用任何編輯器寫 Python,請把一個 tab 展開為 4 個空格
  • 絕對不要混用 tab 和空格,否則容易出現 IndentationError

空格

  • 在 list, dict, tuple, set, 參數的 逗号 “,” 後面加一個空格
  • 在 dict 的 “:” 後面加一個空格
  • 在注釋符号 # 後面加一個空格,但是 #!/usr/bin/python 的 # 後不能有空格
  • 操作符兩端加一個空格,如 +, -, *, /, |, &, =
  • 接上一條,在參數清單裡的 = 兩端不需要空格
  • 括号((), {}, [])内的兩端不需要空格

空行

  • function 和 class 頂上兩個空行
  • class 的 method 之間一個空行
  • 函數内邏輯無關的段落之間空一行,不要過度使用空行
  • 不要把多個語句寫在一行,然後用 “;” 隔開
  • if/for/while 語句中,即使執行語句隻有一句,也要另起一行

換行

  • 每一行代碼控制在 80 字元以内
  • 使用 \ 或 () 控制換行,舉例:
def foo(first, second, third, fourth, fifth,
        sixth, and_some_other_very_long_param):
    user = User.objects.filter_by(first=first, second=second, third=third) \
        .skip(100).limit(100) \
        .all()

text = ('Long strings can be made up '
        'of several shorter strings.')
           

命名

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

1 盡量單獨使用小寫字母‘l’,大寫字母‘O’等容易混淆的字母。

2 子產品命名盡量短小,使用全部小寫的方式,可以使用下劃線。

3 包命名盡量短小,使用全部小寫的方式,不可以使用下劃線。

4 類的命名使用CapWords的方式,子產品内部使用的類采用_CapWords的方式。

5 異常命名使用CapWords+Error字尾的方式。

6 全局變量盡量隻在子產品内有效,類似C語言中的static。實作方法有兩種,一是__all__機制;二是字首一個下劃線。

7 函數命名使用全部小寫的方式,可以使用下劃線。

8 常量命名使用全部大寫的方式,可以使用下劃線。

9 類的屬性(方法和變量)命名使用全部小寫的方式,可以使用下劃線。

9 類的屬性有3種作用域public、non-public和subclass API,可以了解成C++中的public、private、protected,non-public屬性前,字首一條下劃線。

11 類的屬性若與關鍵字名字沖突,字尾一下劃線,盡量不要使用縮略等其他方式。

12 為避免與子類屬性命名沖突,在類的一些屬性前,字首兩條下劃線。比如:類Foo中聲明__a,通路時,隻能通過Foo._Foo__a,避免歧義。如果子類也叫Foo,那就無能為力了。

13 類的方法第一個參數必須是self,而靜态方法第一個參數必須是cls。

import

  • 所有 import 盡量放在檔案開頭,在 docstring 下面,其他變量定義的上面
  • 不要使用 from foo imort *
  • import 需要分組,每組之間一個空行,每個分組内的順序盡量采用字典序,分組順序是:
  1. 标準庫
  2. 第三方庫
  3. 本項目的 package 和 module

不要使用隐式的相對導入(implicit relative imports),可是使用顯示的相對導入(explicit relative imports),如 from …utils import parse,最好使用全路徑導入(absolute imports) 對于不同的 package,一個 import 單獨一行,同一個 package/module 下的内容可以寫一起:

# bad
import sys, os, time

# good
import os
import sys
import time

# ok
from flask import Flask, render_template, jsonify
 
           
  • 為了避免可能出現的命名沖突,可以使用 as 或導入上一級命名空間
  • 不要出現循環導入(cyclic import)

注釋

  • 文檔字元串 docstring, 是 package, module, class, method, function 級别的注釋,可以通過 doc 成員通路到,注釋内容在一對 “”" 符号之間
  • function, method 的文檔字元串應當描述其功能、輸入參數、傳回值,如果有複雜的算法和實作,也需要寫清楚
  • 不要寫錯誤的注釋,不要無謂的注釋
# bad 無謂的注釋
x = x + 1       # increase x by 1

# bad 錯誤的注釋
x = x - 1       # increase x by 1 
           
  • 優先使用英文寫注釋,英文不好全部寫中文,否則更加看不懂

異常

  • 不要輕易使用 try/except
  • except 後面需要指定捕捉的異常,裸露的 except 會捕捉所有異常,意味着會隐藏潛在的問題
  • 可以有多個 except 語句,捕捉多種異常,分别做異常處理
  • 使用 finally 子句來處理一些收尾操作
  • try/except 裡的内容不要太多,隻在可能抛出異常的地方使用,如:
# bad
try:
    user = User()
    user.name = "leon"
    user.age = int(age) # 可能抛出異常
    user.created_at = datetime.datetime.utcnow()

    db.session.add(user)
    db.session.commit() # 可能抛出異常
except:
    db.session.rollback()

# better
try:
    age = int(age)
except (TypeError, ValueError):
    return # 或别的操作

user = User()
user.name = "leon"
user.age = age
user.created_at = datetime.datetime.utcnow()
db.session.add(user)

try:
    db.session.commit()
except sqlalchemy.exc.SQLAlchemyError: # 或者更具體的異常
    db.session.rollback()
finally:
    db.session.close()
           
  • 從 Exception 而不是 BaseException 繼承自定義的異常類

Class(類)

  • 顯示的寫明父類,如果不是繼承自别的類,就繼承自 object 類
  • 使用 super 調用父類的方法
  • 支援多繼承,即同時有多個父類,建議使用 Mixin

字元串

  • 使用字元串的 join 方法拼接字元串
  • 使用字元串類型的方法,而不是 string 子產品的方法
  • 使用 startswith 和 endswith 方法比較字首和字尾
  • 使用 format 方法格式化字元串

比較

  • 空的 list, str, tuple, set, dict 和 0, 0.0, None 都是 False
  • 使用 if somelist 而不是 if len(somelist) 判斷某個 list 是否為空,其他類型同理
  • 使用 is 和 is not 與單例(如 None)進行比較,而不是用 == 和 !=
  • 使用 if a is not None 而不是 if not a is None
  • 用 isinstance 而不是 type 判斷類型
  • 不要用 == 和 != 與 True 和 False 比較(除非有特殊情況,如在 sqlalchemy 中可能用到)
  • 使用 in 操作:
  1. 用 key in dict 而不是 dict.has_key()
# bad
if d.has_key(k):
    do_something()

# good
if k in d:
    do_something()
           
  1. 用 set 加速 “存在性” 檢查,list 的查找是線性的,複雜度 O(n),set 底層是 hash table, 複雜度 O(1),但用 set 需要比 list 更多記憶體空間

其他

  • 使用清單表達式(list comprehension),字典表達式(dict comprehension, Python 2.7+) 和生成器(generator)
  • dict 的 get 方法可以指定預設值,但有些時候應該用 [] 操作,使得可以抛出 KeyError
  • 使用 for item in list 疊代 list, for index, item in enumerate(list) 疊代 list 并擷取下标
  • 使用内建函數 sorted 和 list.sort 進行排序
  • 适量使用 map, reduce, filter 和 lambda,使用内建的 all, any 處理多個條件的判斷
  • 使用 defaultdict (Python 2.5+), Counter(Python 2.7+) 等 “冷門” 但好用的标準庫算法和資料結構
  • 使用裝飾器(decorator)
  • 使用 with 語句處理上下文
  • 有些時候不要對類型做太過嚴格的限制,利用 Python 的鴨子類型(Duck Type)特性
  • 使用 logging 記錄日志,配置好格式和級别
  • 了解 Python 的 Magic Method:A Guide to Python’s Magic Methods, Python 魔術方法指南
  • 閱讀優秀的開源代碼,如 Flask 架構, Requests for Humans
  • 不要重複造輪子,檢視标準庫、PyPi、Github、Google 等使用現有的優秀的解決方案

詳細可以參考 Google 開源項目風格指南 ,Python風格規範

https://zh-google-styleguide.readthedocs.io/en/latest/google-python-styleguide/python_style_rules/

參考文章:

https://my.oschina.net/u/2474096/blog/2248957?from=groupmessage&isappinstalled=0

https://www.cnblogs.com/jiangchunsheng/p/10846052.html