草草的看了一遍,有些設計代碼講解地方因爲我的層次不及,尚不能理解。
基本
- 留白勝於緊湊 |> 一行只寫一條語句
- 明確勝於隱晦 |> 判斷代碼寫的是否優雅的一個規則是:其他開發者是否只閱讀函數的首行和末行就能理解程序的作用
- 錯誤不應被默默的忽略,除非你明確地忽視 |> 沒有指定任何異常類型的
except
語句將捕獲所有的異常,會屏蔽鍵盤發出的KeyboradInterrupt
,使得ctrl +c
無法被正確響應 - 與
*args
的理由類似,kwargs
這類強大的技術應該用在真正需要之處。如果函數的意圖可以通過更簡單更清晰的結構來充分表達,那麼不應該使用這類技術。 - 相比較於運行速度,Python更在意代碼的可讀性,Python把用戶友好看的比性能更重
函數
- Python函數應具有如下特點
-
- 易讀:函數名稱和參數都無需解釋
-
- 易改: 添加新的關鍵字參數不會破壞代碼其他參數
-
- 儘量在移除返回函數結果,函數體的返回點越少越好,當函數不能正確執行時,最好返回
False
或None
- 儘量在移除返回函數結果,函數體的返回點越少越好,當函數不能正確執行時,最好返回
-
- 一個函數只做一件事
類
- 一個函數只做一件事
- 使用@property的目的是將函數與數據相分離
自覺的編程習慣
-
- Python中沒有
private
關鍵字 - 私有屬性和實現細節的主要約定是爲所有的內部變量增加“_”前綴
- 任何不開放給外部使用的方法或者屬性,都應帶下劃線前綴
- 隨時都可以講私有屬性公有化,但是把公有化屬性私有化會困難很多
- 訪問字典時,使用
key in dict
的判斷語法而不是dict.has_keys()
,還可以使用dict.get()處理鍵值爲空時的默認值 - 訪問列表或者數組時,使用
enumerate()
來生成元素位置,比手動維護一個 i += 1 in for 更pythonic -
如果解包是需要賦值,單又不需要其中的某個值,可以使用雙下劃線(__)來代替此位置的值。雙下劃線比單下劃線 更優
- 集合set比列表list的速度更快
- 無法使用with結構時,可以使用
try: do xx \nfinnally: do yy
來代替模塊與包
- 使用import *的代碼更難閱讀,依賴也難以區分
- 如果包內的模塊和子包不需要共享任何代碼,那麼init.py文件留空是最佳實踐。
- 依賴引入的兼容性處理
# 處理不同版本的包名不同,或者使用兼容包模擬另一個包
try:
import functionXX
except ImportError:
import python2_functionXX as functionXX
# 處理2和3不同包引入,設置可以預設2to3的兼容方案
import sys
if sys.version < "3":
import python2_functionXX as functionXX
else:
import functionXX
變量與類型
- Python是動態類型的語言,變量沒有一個固定的類型。變量被實現爲對象的指針。
- 複用變量名對代碼效率提升沒有任何幫助
- 一個變量只賦值一次是良好的實踐
- 變量命名示例:item_string = "sb" \n item_list= [250,520]
- 可變類型:允許in-place改變對象的內容,例如列表和字典,都提供了append()或者pop()等變更自身的方法
- 可變類型不能用作字典的鍵,因爲字典在鍵存儲時使用了哈希方式,不允許鍵發生變化
- 字符串是不可變類型
-
字符拼接:
sb = "me" sb2 = "you" string = "%s %s " %(sb,sb2) # 官方廢棄 string = "{},{}".format(sb,sb2) string = "{0},{1}".format(sb,sb2) # 與C#的方式略有類似 string = "{people1},{people2}".format(people1=sb,people2=sb2) # 最佳風格
文檔
- sphinx是最流行的Python文檔工具
內部
- Python調用棧包含當前Python解釋器正在執行的指令。如果函數f()調用了函數g(),那麼函數f()會先入棧。待g()被調用時則會入棧壓到f()的上面。當g()返回時,它從棧中被彈出,f()會從原來中斷的位置繼續執行。
代碼發佈
- 一般會使用PyInstaller去打包程序,PyInstaller會將程序用到的所有Python庫都放入dist文件夾,所以在分發可執行文件時,需要分發整個dist文件夾
命令行應用
- argparse替代了已經廢棄的optparse模塊,是Python標準庫內置的包。最優使用
- docopt使用函數或者文件的doc位置設置命令行交互。
- click使用註釋器的方式來實現命令交互編寫
- clint可以着色和便利的處理縮進問題
GUI應用
- tkinter庫所有依賴已經捆綁進Python發行版
- PyObjC可以提供OC接口,製作MacOS的專用程序
WSGI服務器
- 相比較於傳統的Web服務器(nginx,apache),wsgi服務器性能好,資源少。
- 比較流行的的服務器有gunicorn,其使用配置比較簡單
代碼管理和改進
- 持續集成,tox |> 打包,測試,部署,Travis-CI |> 分佈式持續集成,可與GitHub無縫集成並評論Pull Request
- 與Jenkins API進行交互最常用的Python工具是python-jenkins
- 服務器自動化:ssh |> Ansible |> 最大的優勢是不要求在客戶端上安裝Python以外的任何東西
- 系統監控: RawSystemInfo |> psutil > glances (擴展版的top,比較綜合,信息全)
- 系統任務管理:ssh |> Fabric
速度優化
- threading 多線程,使用多線程,當Python內核發現某個線程正阻塞在I/O讀寫上時,會切換到另一個線程來使用處理器,直到這個線程也被阻塞和結束
- mutliprocessing 多進程,但是不同進程之間的通信需要注意數據的共享安全
- subprocess用於發起系統調用,推薦Python2用戶使用subprocess32版本,該版本修復了若干bug
- PyPy 是Python的一個純Python實現。使用PyPy代碼不需要任何改動,就能運行得更快。
- future.concurrent 這個包裝了threading和mutliprocessing,用起來方便,但是性能略差。(個人看法)
數據序列化
- 將結構數據轉化爲能夠被共享或者存儲的格式,保留必要的信息傳輸數據的接收端(或者從存儲中讀取數據時)能夠在內存中重建對象
- 可以讓被序化的數據佔用最小化,便於最小化磁盤需求或者網絡帶寬需求
- pickle模塊在遇到錯誤和惡意結構的數據時是不安全的,不要使用pickle對來源不明的數據進行反序列化
- 跨語言序列化可以使用谷歌的protobuf
網絡編程
- asyncio 提供異步事件循環來管理與非阻塞套接字或者隊列通信,以及任意用戶定義的協程。asyncio目前仍不成熟。臨時性的存在於標準庫中
- gevent 因輕量,與底層C庫libev緊耦合,性能很高,而被廣泛使用
- pika 提供一個清涼的AMQP客戶端,用於連接RabbitMQ或者其他消息代理