我的總結——『Python編碼規範』

規範

【強制 + 強制】【挑選『靜態檢查』工具,並自始至終都嚴格使用】

簡單來講,就是:
1. Pylint
2. Flake8
3. pytest

一開始就要使用,而且從嚴使用(發點時間瞭解這幾個工具,帶來的收益是無限的,若是你是比較正式的項目的話)。

【強制+】【多寫UT】

其餘編程語言,同理。

有一份UT在手,重構起來,內心放心不少。

Python的話,只須要了解unittest就夠了,pytest也能夠。

【強制】【文件編碼 & Unicode】

PS:下面這幾條,能幫你避免不少無聊的編碼解碼問題,因此我以爲很重要python

  1. 使用 4 空格縮進,禁用任何 TAB 符號
  2. 源碼文件使用 UTF-8 無 BOM 編碼格式
  3. 老是使用 Unix \n 風格換行符
  4. 在每個 py 文件頭,都添加以下內容:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
 

# 只導入 future 空間的這兩個特性就夠了,其餘特性容易形成其餘方面的『不兼容』,沒有使用的必要性。
from __future__ import (absolute_import, unicode_literals)

因此,你須要瞭解 editorconfig 這個東西,從根源上統一規範,不符合規範的,直接拒絕 PUSH or MERGE

###【強制】【命名】編程

  1. class,function 該如何命名,不贅述,嚴格照着PEP8作就好了,不用多想。
  2. 全局變量(全局變量,通常是常量,咱們認爲:凡是全局的,都是常量),應該始終使用全大寫,如:
GLOBAL_PUBLIC = "G1"
_GLOBAL_PRIVATE = "G2"

class Person:
    _GLOBAL_IN_CLASS = 'G3'
    

按照這條要求,其實不少庫or開源庫,都是不符合要求的。爲何這麼強硬呢?
Python中的變量定義,是不分『聲明』、『定義』、『初始化』、『賦值』這幾個概念的,因此一個
a = 1
若是沒有上下文,你是很難肯定其做用域的,也很難肯定 這究竟是初始化仍是賦值(a已經存在過),
若是全局變量還不用全大寫,帶來的麻煩只會更多。

若是始終堅持這個原則,將會給代碼的可讀性帶來極大提高。

【強制】定義枚舉,始終加 Enum後綴;定義異常始終加Exception後綴;定義mixin,始終加Mixin後綴,如

class DirectionEnum:
    UP = 1
    DOWN = 2
    
    
class MyException(Exception):
    pass
class MyError(Exception):
    pass
    
class SomeMixin:
    pass

【強制】【強化private的概念】

即:最小知識原則,對外暴露的東西越少越好

翻譯成大白話就是:
1. 實例屬性,通常定義成private的
2. class,對外提供的方法越少越好
3. module,對外提供的接口越少越好
4. package,對外提供的 module 越少越好

翻譯成代碼就是:
1. 項目佈局
package/
    __init__.py
    _private_mod.py
    public_mod.py    
    
2. 某模塊內容
public_mod.py
PUBLIC_GLOBAL = 'G1'
_PRIVATE_GLOBAL = 'G2'
class _Class:
    pass
class PublicClass:
    _PRIVATE_GLOBAL = 'G3'
    
    def __init__(self, name,age):
        self._name = name
        self._age = age
    def public_method(self):
        pass
    def _private(self):
        pass
        

全部東西,一開始就要定義成私有的,等到確實須要開放訪問了,纔開放出去。

【強制&重要】【關注公開接口的複雜性】

最好的接口是這樣的,調用者無腦使用
def interface():
    pass
    
次等接口是這樣的
def interface(param1):
    pass
    
次次等接口是這樣的
def interface(p1, p2):
    pass

最大忍受限度的接口是這樣的
def interface(p1, p2, p3='SOME DEFAULT'):
    pass
def interface(p1, *args):
    pass
    
不可接受的接口是這樣的
def interface(p1, p2, **kwargs):
    pass

使人無語的接口是這樣的
def interface(*args, **kwargs):  
# 儘可能不要使用 **kwargs, 某些流行庫有這樣的毛病,我是以爲:極大地增長了調用者的心理負擔,反映了接口設計者的懶惰
    pass
    
一直以爲,**kwargs只適用於極少數明確的場合,而且須要輔以很明確的文檔說明(解釋爲何要使用),然而現實是,這個
特性已經被你們濫用了,有必要單獨說明之。

PS:我一直以爲,濫用 **kwargs 的API,幾乎都不是好 API,無形增長心理負擔。框架

【推薦】【以package去設計命名空間,而不是基於module】

【推薦】【瞭解以下內容】

__init__.py 的做用

__main__.py 的做用

if __name__ == '__main__': 的做用

Python的命名空間加載機制,即:sys.path sys.modules 的內容

【推薦】【合理設計項目目錄結構】

若是是使用某種框架(如Django),那麼按照框架的規範來;若是是「非框架」項目,則按照以下結構

project
    project/
        __init__.py
        core/
        utils/
        constants/
        
        
        __main__.py
        
    tests/
    docs/
    examples/
    README.md
    .pylintrc
    .flake8
相關文章
相關標籤/搜索