Django之代碼風格

1 代碼風格

稍微關注一下下面這些代碼標準風格指導規則將會對你大有益處,咱們高度建議你通讀詞章,即使你此時可能正想跳過它。javascript

1.1 讓你的代碼保持可讀性的重要性

代碼在讀方面的重要性賽過寫。一個代碼塊幾分鐘編寫,花幾個小時調試,而後有可能不再會有人去碰它。然而當你去閱讀那些昨天或者甚至10年之前編寫的代碼,清晰一致的代碼風格就變得很是有用。清晰移動的代碼可以讓你不用去費勁去理解代碼的不一致性,從而節省了本身的腦力,而且使代碼易於維護,提升了各類規模項目的總體質量。css

下面這些方法讓你"多走一千米"使你的代碼儘量清晰易讀:html

  • 避免縮寫的變量名稱
  • 寫出你的函數的參數名稱
  • 對你的類和方法要寫註釋文檔
  • 要對你的代碼加註釋
  • 把重複的代碼重構爲可複用的函數和方法
  • 使函數和方法短一點,一個好的經驗法則是讀函數和方法代碼時不須要滾動鼠標(也就是函數或方法的長度不能大於一個屏幕的顯示高度)

當你長時間不碰某段代碼後,再從新拿起這段代碼,你能很容易地找到當初是從哪兒中斷編寫工做的html5

縮寫變量名是很是使人討厭的。好比:當你看到一個balance_sheet decrease的變量名時,解釋它確定要比解釋縮寫版的bsd或者bal_s_d要容易。這種類型的縮寫可能會幫你省一點輸入時間,可是這種節省是以幾小時甚至幾天的技術(代碼閱讀)債爲代價,因此這種節省不值當。java

1.2 PEP8

PEP8是一個官方的Python代碼風格指南。咱們建議詳細認真地閱讀它並學會遵照PEP8的代碼約定:(http://www.python.org/dev/peps/pep-0008/)node

PEP8描述了相似下面這樣的代碼約定:python

  • 「每一級代碼縮進使用4個空格」
  • 「獨立的頂級函數或者類定義語句下面必須有2個空行」
  • 「類中的方法定義之間必須用一個空行隔開」

在Django項目中的全部python代碼文件必須遵照PEP8。若是你記不住PEP8的代碼規則,你能夠爲你的代碼編輯器找一個檢查你輸入代碼是否符合PEP8的插件。git

當一個有經驗的Python程序員在Django項目中看到對PEP8規範的嚴重違反,即使他當時什麼也不說,也在想這是一件很壞的事情。關於這一點,必定要相信咱們。程序員

警告:不要改變現存項目的代碼約定angularjs

PEP8的代碼規範通常僅對新的Django項目產生約束,若是你新參與一個項目,這個項目使用的代碼約定和PEP8規範不一樣,那你就遵照項目目前的代碼約定便可。

請閱讀PEP8規範的第8章節:愚蠢的一致性是使人討厭的想法,這個規則正好適用於咱們此時不死守PEP8規範的狀況:

**構建技巧:使用flake8檢查代碼質量

flake8這個項目由Tarek Ziadé發起,由PyCQA小組維護,這是一個很是有用的檢查項目代碼風格、質量和邏輯錯誤的命令行工具。當你在本地開發時,能夠把它做爲持續集成的一個工具組件使用。

1.2.1 79字符限制

這不是開玩笑,我仍舊把命令行控制檯控制在80個字符寬度

--- Barry Morrison:系統工程師兼本書每個版本的審閱者

根據PEP8規範,每行的文本長度限制是79個字符。這樣設計是由於79在文本環繞編輯器裏面比較安全,開發團隊在無需代碼可讀性的前提下即可以適應。

而後PEP8也提供一個彈性措施:能夠爲專屬團隊項目把這個限制提到99個字符。咱們理解這個所謂的專屬團隊項目也就是非開源項目。

下面是咱們的偏好設定:

  • 一個開源項目的行字符數必須硬性限制在79個字符之內,咱們的經驗已經證實:開源項目的代碼貢獻者和訪問者會對代碼行長度這個問題有抱怨。
  • 在私有項目上,咱們把代碼行長度限制放寬到99個字符,充分利用現代的顯示器。

請閱讀:(http://www.python.org/dev/peps/pep-0008/#maximum-line-length)

提示:Aymeric Augustin關於代碼行長度問題的觀點

Django核心開發者Aymeric Augustin曾說:"把代碼行長度限制在79個字符這個限制,不是給變量、函數、類起糟糕名字的合理理由。給變量起一個可讀性的名字比遵照幾十年之前的硬件限制而引發的約束更重要。"

1.3 關於import語句的代碼規範

PEP8規範建議import語句必須下面的規則排序分組:

  1. 標準庫導入
  2. 相關的第三方庫導入
  3. 本地應用或者特定庫的導入

打咱們開發一個Django項目時,import語句應該像下面例子這樣

Example1.1

# Stdlib imports
from __future__ import absolute_import
from math import sqrt
from os.path import abspath

# Core Django imports
from django.db import models
from django.utils.translation import ugettext_lazy as _

# Third-party app imports
from django_extensions.db.models import TimeStampedModel

# Imports from your apps
from splits.models import BananaSplit

(注意:你在實際項目中不須要像上面這個例子這樣註釋import語句,此處的註釋只是爲了說明例子演示的規則)

Django項目中import語句的順序是:

  1. 標準庫導入
  2. 導入Django內建資源
  3. 從第三方App的導入,包括那些與Django沒有關係的App
  4. 從Django項目所建App的導入(你將在第四章讀到Django App相關的內容,第四章的主題是App設計基礎)

1.4 使用顯式相對路徑導入

當你寫代碼時,使用顯式相對路徑導入這是很重要,由於這樣可讓你便於移動、重命名、版本化你的模塊包。在Python編程中,使用顯式相對路徑導入能夠減小你的模塊包的硬代碼量要求,能夠把模塊包從它緊密依賴的架構環境中獨立出來。由於Django App也是包的形式,因此個編碼規則也適用於Django App編程。

爲了演示顯式相對路徑導入方式的益處,讓咱們看一個例子:

假定下面的代碼片斷摘自一個冰激凌消費量跟蹤Django項目,其中消費的冰激凌品類包括大家曾經吃過的華夫、甜筒、暴風雪。

哦,不,你的cones Django App裏面有全路徑硬編碼導入,這太糟了:

Bad Example 1.1 
# cones/views.py
from django.views.generic import CreateView
# DON'T DO THIS!
# Hardcoding of the 'cones' package
# with implicit relative imports
from cones.models import WaffleCone 
from cones.forms import WaffleConeForm 
from core.views import FoodMixin

class WaffleConeCreateView(FoodMixin, CreateView):
    model = WaffleCone
    form_class = WaffleConeForm

確實,你的cones App在你的冰激凌消費量跟蹤項目裏面能夠正確執行,可是它裏面的那些硬編碼導入會使它自己的可移植性和可複用性很是差:

  • >若是你想在另一個跟蹤通用甜食的Django項目中複用你的cones App,而同時卻由於命名衝突不得不修改App的名字,你會怎樣作?
  • >若是你有時候只是簡單想改App的名字,那怎麼作?

若是硬編碼絕對路徑導入,你在修改時就不能只改App的名字,而是不得不找到全部的此類導入並所有修改。雖然手工修改他們不難,但在你駁回相對路徑導入這個辦法前,請想一想與那些帶有各類各樣的附加功能模塊的App相比,上面這個例子是很是簡單的。

如今讓咱們把上面這個硬編碼絕對路徑導入的代碼片斷改形成相對路徑導入的好代碼,下面是修正後的例子:

Example 1.2
# cones/views.py
from __future__ import absolute_import
from django.views.generic import CreateView

# Relative imports of the 'cones' package
from .models import WaffleCone
from .forms import WaffleConeForm
from core.views import FoodMixin

class WaffleConeCreateView(FoodMixin, CreateView):
    model = WaffleCone
    form_class = WaffleConeForm

另一個具體的優點是咱們能夠當即辨別出本地導入和全局導入,強調Python包是一個代碼單元這一點。


提示:"from future import absolute_import"語句的使用

Python3以一種更好的方式更新和改進了import語句運行機制。幸運的是:咱們可使用from __future__ import absolute_import這條語句作到對Python2.7向後兼容。即便你不計劃使用Python3,可是考慮到下面表中的相對路徑導入,這也是一個很棒的方法。


總結一下,下面的表格給出了不一樣的Python導入類型以及在Django項目中什麼時候使用它們。

導入代碼 導入類型 使用場景
from core.views import FoodMixin 絕對路徑導入 從目前App外部導入
from .models import WaffleCone 顯式相對路徑導入 從目前App的另外一個模塊導入
from models import WaffleCone 隱式相對路徑導入 從目前App的另外一個模塊導入,但不推薦這麼作

表格 1.1 導入類型 絕對路徑導入 VS 顯式相對路徑導入 VS 隱式相對路徑導入

養成使用顯式相對路徑導入的習慣,這很是容易作到,並且這也是一個Python程序員開發好習慣。


提示:PEP328規範不和PEP8規範衝突嗎?

請看Python創始人吉多·範羅蘇姆是怎麼說的:


相關閱讀: http://www.python.org/dev/peps/pep-0328/

1.5 避免使用import *

在咱們全部工做中的99%的狀況下,咱們都應該顯式導入每一個模塊:

Example 1.3

from django import forms 
from django.db import models

不要寫下面這樣的代碼:

Bad Example 1.2
# ANTI-PATTERN: Don't do this! 
from django.forms import * 
from django.db.models import *

不這樣作的緣由是避免銀式導入另一個python模塊的內部變量而致使覆蓋目前模塊命名空間內的變量,那樣會致使不可預知的結果,有時甚至是災難性的結果。

咱們將在本書內容中講解一個此規則的例外狀況,這個例子將在第五章(章名之後再譯)中出現。

咱們再來看一下上面的反面案例,在Django models庫模塊和Django forms庫模塊中都有一個叫CharField的類,models庫中的類會覆蓋掉forms庫中的同名類,這種狀況也會發如今Python內建庫和其餘第三方庫之間,那樣就會致使關鍵功能特性對象被覆蓋。


警告:Python命名衝突 假如你試圖導入兩個具備相同命名的對象時,也會發生相同的類似的命名覆蓋問題

Bad Example 1.3
# ANTI-PATTERN: Don't do this! 
from django.forms import CharField 
from django.db.models import CharField

使用import *方式,就像一個貪婪的客人進入冰激凌店後試品了全部三十一種口味冰激凌,最後卻只買了1到2個球。若是你只使用模塊中1到2個對象,就不要試圖導入模塊中全部的對象引用。

固然若是客人走出冰激凌店的時候捧着一個巨大的冰激凌碗,而裏面盛着幾乎全部口味的冰激凌球,固然,這是另一回事了。

1.6 Django代碼風格

這一節內容將會覆蓋Django官方代碼約定規範以及非官方可是廣泛被接受的代碼規範

1.6.1 考慮一下Django代碼風格指南

不用說,熟悉通用Django風格約定是個好作法。實際上,Django內部有它本身的代碼風格指南,這個指南基於PEP8擴展而成。

另外,若是有內容不在官方代碼標準裏面明確指明,那在Django社區也會有很是常見的此類代碼風格約定能夠供你在項目中使用。

1.6.2 在ULR模式名稱定義裏使用下劃線而不是破折號(中劃線)

咱們平常使用下劃線(字符"-")而不是破折號(字符"-"),這樣作不只僅是由於更Pythonic,並且對更多的IDE和文本編輯器也更友好。注意咱們這裏下面例子裏說的是url()函數的name參數的值,而不是瀏覽器裏面實際輸入的URL片斷(譯註:正則表達式那段)。

像下面這樣在url名稱裏面用中劃線是錯誤的方式:

Bad Example 1.4
patterns = [
    url(regex='^add/$',
        view=views.add_topping,
        name='add-topping'),
    ]

正確的方式,是在url名稱裏面用下劃線:

Example 1.4
patterns = [
    url(regex='^add/$',
        view=views.add_topping,
        name='add_topping'),
    ]

注意:咱們這裏指的是url函數name參數的值,不是瀏覽器實際輸入的URL片斷,在URL片斷裏面用中劃線是能夠的,(好比:regex='^add-topping/$')。

1.6.3 在模板block名稱裏面用下劃線,而不是中劃線

與在URL模式名稱裏面用下劃線同樣的緣由,咱們建議在定義模板block時也使用下環線:這樣的話就能夠更Pythonic且對編輯器更友好。

1.7 選擇JavaScript、HTML和CSS的代碼風格指南

1.7.1 JavaScript代碼風格指南

不像Python有官方的代碼風格指南,JavaScript不存在官方代碼風格指南,相代替的是,有不少我的或公司編纂的的javascript非官方代碼風格指南:

在Django或JavaScript社區對於上面的代碼風格指南都沒有一致的意見,你只須要選擇你偏好的並堅持它便可。

固然,若是你使用一個自帶代碼風格約定的JavaScript框架,你就應該使用它自帶的代碼約定。好比ember.js就有其自帶的代碼約定。


包提示:JSCS代碼風格審查器

JSCS( http://jscs.info/ ) 是一個JavaScript代碼風格審查工具。它預設好幾種JavaScipt代碼風格指南的編碼規則,包括前面列出的代碼約定中的一些。有面向好幾種代碼文本編輯器的JSCS插件,還有面向Gulp和Grunt之類構建工具的JSCS檢查任務腳本。


1.7.2 HTML和CSS代碼風格指南


包提示:CSScomb

CSScomb ( http://csscomb.com/ )一個CSS代碼風格格式化工具。它檢查你預配置好的風格的代碼一致性和CSS屬性的排序規則,就像JSCS同樣,CSScomb也有面向文本編輯器的插件和麪向任務構建工具的插件,其中包括面向brunch這樣的HTML5構建工具的版本。


1.8 不要面向IDE(或者文本編輯器)編程

某些程序員在作出關於項目的文件佈局和封裝實現的選擇時多是基於IDE(集成開發環境)的特性來考慮,這對於那些選擇不一樣不一樣開發工具的程序員試圖來探索你的項目代碼時將變得很是困難。

常常假設你身邊的程序員和你採用不一樣的工具,而且你的項目代碼結構足夠清晰易懂,以便於他們即便使用NotePad或者Nano均可以探索你的代碼。

好比:深思模板標籤且查看標籤源碼對於那些使用功能有限的IDE工具的程序員來講是很是困難切耗時的,所以咱們使用約定的標籤模塊命名方式:_tags.py。

1.9 小結

這一章包括了咱們推薦的代碼風格指南以及解釋咱們偏好每一個技巧的緣由。

即便你不遵照咱們推薦的代碼約定,也請你遵照任何一個統一的代碼風格指南。有多種代碼風格的項目代碼是不易維護的,而且會拖慢快發速度且提升發生開發失誤的可能性。

相關文章
相關標籤/搜索