前言
對我來說,以前每次面試是我審視自己,檢驗自己的一種方式。每次準備面試,以及被面試官問住的時候才會發現,其實我python我學的還不夠好。工作中也是,可以從其他的同事那裡獲得成長。但是我今天說的是,我也在自己總結和思考最佳實踐
這件事。
我想很多人都會有意識的去讀一些PEP(Python Enhancement Proposals)。瞭解語言設計者當時的考慮,這些文案也是經過很長時間的討論最後才實施的。既然想用好這門語言,必然需要理解設計之美。比如我聽說gvanrossum使用emacs作為編輯器,我也使用emacs,就是希望我可以更貼近一些python。
本文根據 The Best of the Best Practices (BOBP) Guide for Python 和 Khan’s style-guides中對於開發中一些事物的理解和看法,有出至PEP,也有一些python界知名開發者,我加入了一些我自己的理解和看法。
價值觀
“Build tools for others that you want to be built for you.” – Kenneth Reitz (Requests等知名庫作者)
你自己都不想用的東西做出來有什麼意義呢?
“Simplicity is alway better than functionality.” – Pieter Hintjens (ZeroMQ)
我對函數語言程式設計的看法一直是看場景
,甚至於我經常會對比效能,義無反顧的使用效能最好的,但是程式碼又不難懂和繁瑣的
“Fit the 90% use-case. Ignore the nay sayers.” – Kenneth Reitz
程式設計師都有完美主義情懷,但是其實往往我們是在偏激的看事情 – 使用者其實不case
“Beautiful is better than ugly.” – PEP 20
開發參考
“Explicit is better than implicit” – PEP 20
不要留坑,我經常看到一些複雜的程式碼,這些程式碼的作者寫的時候明顯知道自己在做什麼,但是別人很難維護和看懂.
所以我對自己的職業的基本要求就是: 那天我離職了,後來接手的人不會經常罵我
“Readability counts.” – PEP 20
“Anybody can fix anything.” – Khan’s style-guides
我現在更多不是程式碼炫技,我經常思考的怎麼讓最少的程式碼,最簡單的設計結構滿足當前需求,也能給未來一段時間裡也有擴充套件性
Fix each broken window (bad design,wrong decision,or poor code) as soon as it is discovered.
我們改bug有個原則 – 測試要覆蓋到出bug的地方。每個人內心都有很高的程式碼質量的要求
“Now is better than never.” – PEP 20
明日復明日,明日何其多。我們在程式碼review的時候,問題需要在提出的時候就去改,永遠不會說下一次再說,因為下一次大多時候是沒有下一次了
Test ruthlessly. Write docs for new features.
Even more important that Test-Driven Development–Human-Driven Development
一些細節
PEP8
很多人是排斥的,假如你想讓未來部門有自己的風格,習慣。讓新人馬上上手接受,PEP8是一個非常明智的選擇
檔案開頭
新的檔案的開頭需要加一些docstring。描述檔案的作用,編輯者,修改原因和日期等幫助閱讀者的描述.
不要新增#!/usr/bin/python
(除非這個檔案未來是一個可執行的檔案),copyright,__author__或者其他內容.
第一行建議新增# coding-utf-8
命名
- Variables,functions,methods,packages,moduleslower_case_with_underscores
- Classes and ExceptionsCapWords
- Protected methods and internal functions_single_leading_underscore(self,…)
- Private methods__double_leading_underscore(self,…)
- ConstantsALL_CAPS_WITH_UNDERSCORES
- Avoid one-letter variables (esp. l,O,I).永遠不要使用沒有意義的單字元作為變數名
PS: 這點可以折中,假如一個程式碼塊程式碼邏輯很清晰,而 這個短的便令也只是過程中的一個間接變數之類的情況下是可以接受的
Good or Bad
列舉一些正確和錯誤的用法.
Avoid redundant labeling.
1 2 3 4 5 6 7 8 9 10 11 |
# Good import audio core = audio.Core() controller = audio.Controller() # Bad import audio core = audio.AudioCore() controller = audio.AudioController() |
不要使用重複意義的標籤
Prefer “reverse notation”.
1 2 3 4 5 6 7 8 9 |
# Good elements = ... elements_active = ... elements_defunct = ... # Bad elements = ... active_elements = ... defunct_elements ... |
Avoid getter and setter methods.
1 2 3 4 5 |
# Good person.age = 42 # Bad person.set_age(42) |
Indentation
永遠不要Tab和空格混用。使用4個空格作為python縮排
Imports
Import entire modules instead of individual symbols within a module.
PS: 這個時候可以參考tornado的程式碼用法.
比如現在有這樣一個包
1 2 3 4 |
$ tree └── canteen ├── __init__.py ├── sessions.py |
1 2 3 4 5 6 7 8 |
# Good import canteen import canteen.sessions from canteen import sessions # Bad from canteen import get_user # Symbol from canteen/__init__.py from canteen.sessions import get_session # Symbol from canteen/sessions.py |
PS: 除非這個第三方模組的文件顯式的要求這些寫
Splitting tricky lines
1 2 3 4 5 6 7 8 |
# Bad: badge_name = badges.topic_exercise_badges.TopicExerciseBadge.name_for_topic_key_name(self.key().name()) # Good: badge_name = (badges.topic_exercise_badges.TopicExerciseBadge .name_for_topic_key_name(self.key().name())) # Bad: self.redirect("/class_profile?selected_graph_type=%s |
我新增的規則
from … import …
1 2 3 4 5 6 7 8 9 10 |
# Bad from aa import alonglonglonglonglong,alonglonglonglonglonglonglonglonglong, alonglonglonglonglonglong # Good from aa import (alonglonglonglonglong,alonglonglonglonglonglonglonglonglong, alonglonglonglonglonglong) from aa import (alonglonglonglonglong,alonglonglonglonglonglonglonglonglong, alonglonglonglonglonglong,alonglonglonglonglonglonglong, alonglonglonglonglonglong2) # Good。 當引入的函式/類/變數很多時,也可以選擇空 4 個空格的方式,而不需要和首行的左括號後對齊 |
相對引用(relative import) 和 絕對引用(absolute import)
1 2 3 4 5 6 7 8 9 10 11 12 |
$cat xx/models/user/consts.py # 如果想引用這個變數 TMP = 1 $cat xx/views/user.py from xx.models.user.consts import TMP # recommended。 # 假如模組層級>=3。 比如 xx/models/user/consts.py 就在根目錄下的第 3 級。 如果其他當前目錄下原始檔需要呼叫它的內容。 也可以選擇相對引用 $cat xx/models/user/main.py # 需要和 consts.py 在一個目錄下才可以 from consts import TMP # Bad from .consts import TMP # Good # 而且只能在包內相對引用。 包外都需要絕對引用 |