沒錯,編碼風格是一個不太討巧的話題,不過這里仍然要聊一下。
Python具有其他語言少有的絕佳質量[②](#anchor12):使用縮進來定義代碼塊。乍一看,似乎它解決了一個由來已久的“往哪里放大括號?”的問題,然而,它又帶來了“如何縮進?”這個新問題。
而Python社區則利用他們的無窮智慧,提出了編寫Python代碼的PEP 8[③](#anchor13)([http://www. python.org/dev/peps/pep-0008/](http://www.python.org/dev/peps/pep-0008/))標準。這些規范可以歸納成下面的內容。
- 每個縮進層級使用4個空格。
- 每行最多79個字符。
- 頂層的函數或類的定義之間空兩行。
- 采用ASCII或UTF-8編碼文件。
- 在文件頂端,注釋和文檔說明之下,每行每條`import`語句只導入一個模塊,同時要按標準庫、第三方庫和本地庫的導入順序進行分組。
- 在小括號、中括號、大括號之間或者逗號之前沒有額外的空格。
- 類的命名采用駱駝命名法,如`CamelCase`;異常的定義使用`Error`前綴(如適用的話);函數的命名使用下劃線分隔的小寫字母,如`separated_by_underscores`;用下劃線開頭定義私有的屬性或方法,如`_private`。
這些規范其實很容易遵守,而且實際上很合理。大部分程序員在按照這些規范寫代碼時并沒有什么不便。
然而,**犯錯在所難免**,保持代碼符合PEP 8規范的要求仍是一件麻煩事。工具**pep8**([https:// pypi.python.org/pypi/pep8](https://pypi.python.org/pypi/pep8))就是用來解決這個問題的,它能自動檢查Python文件是否符合PEP 8要求,如示例1.1所示。
**示例1.1 運行pep8**
```
$ pep8 hello.py
hello.py:4:1: E302 expected 2 blank lines, found 1
$ echo $?
1
```
pep8會顯示在哪行哪里違反了PEP 8,并為每個問題給出其錯誤碼。如果違反了那些必須遵守的規范,則會報出**錯誤**(以E開頭的錯誤碼),如果是細小的問題則會報**警告**(以W開頭的錯誤碼)。跟在字母后面的3位數字則指出具體的錯誤或警告,可以從錯誤碼的百位數看出問題的大概類別。例如,以E2開頭的錯誤通常與空格有關,以E3開頭的錯誤則與空行有關,而以W6開頭的警告則表明使用了已廢棄的功能。
社區仍然在爭論對并非標準庫一部分的代碼進行PEP 8驗證是否是一種好的實踐。這里建議還是考慮一下,最好能定期用PEP 8驗證工具對代碼進行檢測。一種簡單的方式就是將其集成到測試套件中。盡管這似乎有點兒極端,但這能保證代碼一直遵守PEP 8規范。8.7節中將介紹如何將pep8與tox集成,從而讓這些檢查自動化。
OpenStack項目從一開始就通過自動檢查強制遵守PEP 8規范。盡管有時候這讓新手比較抓狂,但這讓整個代碼庫的每一部分都保持一致,要知道現在它有167萬行代碼。對于任何規模的項目這都是非常重要的,因為即使對于空白字符的順序,不同的程序員也會有不同的意見。
也可以使用`--ignore`選項忽略某些特定的錯誤或警告,如示例1.2所示。
**示例1.2 運行pep8時指定`--ignore`選項**
```
$ pep8 --ignore=E3 hello.py
$ echo $?
0
```
這可以有效地忽略那些不想遵循的PEP 8標準。如果使用pep8對已有的代碼庫進行檢查,這也可以暫時忽略某些問題,從而每次只專注解決一類問題。
>注意
> 如果正在寫一些針對Python的C語言代碼(如模塊),則PEP 7([http://www.python.org/dev/ peps/pep-0007/](http://www.python.org/dev/peps/pep-0007/))標準描述了應該遵循的相應的編碼風格。
還有一些其他的工具能夠檢查真正的編碼錯誤而非風格問題。下面是一些比較知名的工具。
- pyflakes(<https://launchpad.net/pyflakes>),它支持插件。
- pylint(<https://pypi.python.org/pypi/pylint>),它支持PEP 8,默認可以執行更多檢查,并且支持插件。
這些工具都是利用靜態分析技術,也就是說,解析代碼并分析代碼而無需運行。
如果選擇使用pyflakes,要注意它按自己的規則檢查而非按PEP 8,所以仍然需要運行pep8。為了簡化操作,一個名為flake8(<https://pypi.python.org/pypi/flake8>)的項目將pyflakes和pep8合并成了一個命令,而且加入了一些新的功能,如忽略帶有`#noqa`的行以及通過入口點(entry point)進行擴展。
為了追求優美而統一的代碼,OpenStack選擇使用flake8進行代碼檢查。不過隨著時間的推移,社區的開發者們已經開始利用flake8的可擴展性對提交的代碼進行更多潛在問題的檢查。最終flake8的這個擴展被命名為hacking(<https://pypi.python.org/pypi/hacking>)。它可以檢查`except`語句的錯誤使用、Python 2與Python 3的兼容性問題、導入風格、危險的字符串格式化及可能的本地化問題。
如果你正開始一個新項目,這里強烈建議使用上述工具之一對代碼的質量和風格進行自動檢查。如果已經有了代碼庫,那么一種比較好的方式是先關閉大部分警告,然后每次只解決一類問題。
盡管沒有一種工具能夠完美地滿足每個項目或者每個人的喜好,但flake8和hacking的結合使用是持續改進代碼質量的良好方式。要是沒想好其他的,那么這是一個向此目標前進的好的開始。
>提示
> 許多文本編輯器,包括流行的GNU Emacs(<http://www.gnu.org/software/emacs/>)和vim(<http://www.vim.org/>),都有能夠直接對代碼運行pep8和flake8這類工具的插件(如Flycheck),能夠交互地突出顯示代碼中任何不兼容PEP 8規范的部分。這種方式能夠非常方便地在代碼編寫過程中修正大部分風格錯誤。
這個工具集很容易擴展。我在OpenStack中用`hacking`擴展來擴展這個工具集,例如,我添加了一個檢查,用于找出本應該聲明為靜態的方法。這部分內容會在11.1節中談及。
> [②](#ac12) 你可能有不同意見。
> [③](#ac13) *PEP 8 Style Guide for Python Code*, 5th July 2001, Guido van Rossum, Barry Warsaw, Nick Coghlan
- 內容提要
- 中文版序
- 前言
- 第1章 項目開始
- 1.1 Python版本
- 1.2 項目布局
- 1.3 版本編號
- 1.4 編碼風格與自動檢查
- 1.5 Joshua Harlow訪談
- 第2章 模塊和庫
- 2.1 導入系統
- 2.2 標準庫
- 2.3 外部庫
- 2.4 框架
- 2.5 Doug Hellmann訪談
- 第3章 管理API變化
- Christophe de Vienne訪談
- 第4章 時區陷阱
- 第5章 文檔
- 5.1 Sphinx和reST入門
- 5.2 Sphinx模塊
- 5.3 擴展Sphinx
- 第6章 分發
- 6.1 簡史
- 6.2 使用pbr打包
- 6.3 Wheel格式
- 6.4 包的安裝
- 6.5 和世界分享你的成果
- 6.6 Nick Coghlan訪談
- 6.7 入口點
- 6.7.1 可視化的入口點
- 6.7.2 使用控制臺腳本
- 6.7.3 使用插件和驅動程序
- 第7章 虛擬環境
- 第8章 單元測試
- 8.1 基礎知識
- 8.2 fixture
- 8.3 模擬(mocking)
- 8.4 場景測試
- 8.5 測試序列與并行
- 8.6 測試覆蓋
- 8.7 使用虛擬環境和tox
- 8.8 測試策略
- 8.9 Robert Collins訪談
- 第9章 方法和裝飾器
- 9.1 創建裝飾器
- 9.2 Python中方法的運行機制
- 9.3 靜態方法
- 9.4 類方法
- 9.5 抽象方法
- 9.6 混合使用靜態方法、類方法和抽象方法
- 9.7 關于super的真相
- 第10章 函數式編程
- 10.1 生成器
- 10.2 列表推導
- 10.3 函數式函數的函數化
- 第11章 抽象語法樹
- 11.1 用抽象語法樹檢查來擴展flake8
- 11.2 Hy
- 11.3 Paul Tagliamonte訪談
- 第12章 性能與優化
- 12.1 數據結構
- 12.2 性能分析
- 12.3 有序列表和二分查找
- 12.4 namedtuple和slots
- 12.5 memoization
- 12.6 PyPy
- 12.7 通過緩沖區協議實現零復制
- 12.8 Victor Stinner訪談
- 第13章 擴展與架構
- 13.1 多線程的注意事項
- 13.2 多進程與多線程
- 13.3 異步和事件驅動架構
- 13.4 面向服務架構
- 第14章 RDBMS和ORM
- 14.1 用Flask和PostgreSQL流化數據
- 14.2 Dimitri Fontaine訪談
- 第15章 Python 3支持策略
- 15.1 語言和標準庫
- 15.2 外部庫
- 15.3 使用six
- 第16章 少即是多
- 16.1 單分發器
- 16.2 上下文管理器
- 第17章 延伸閱讀
- 版權信息
- 版權聲明
- 歡迎來到異步社區!
- 異步社區的來歷
- 社區里都有什么?
- 購買圖書
- 下載資源
- 與作譯者互動
- 靈活優惠的購書
- 紙電圖書組合購買
- 社區里還可以做什么?
- 提交勘誤
- 寫作
- 會議活動早知道
- 加入異步