Python語言基礎
語言特性
- 動態強類型語言(很多人誤覺得是弱類型)
- 動態仍是靜態指的是編譯期仍是運行期肯定類型
- 強類型指的是不會發生隱式型轉換
優缺點
- 膠水語言,輪子多,應用普遍
- 語言靈活,生產力高
- 性能問題,代碼維護問題,Python2/3兼容問題
鴨子類型
- 關注點在對象的行爲,而不是類型(duck typing)
- 好比 file,StringIO,socket 對象都支持 read/write 方法(file like object)
- 再好比定義了 __iter__ 魔術方法的對象能夠用 for 迭代
monkey patch
- 所謂的 monkey patch 就是運行時替換
- 好比 gevent 庫須要修改內置的 socket
- from gevent import monkey; monkey.patch_socket()
自省(Introspection)
- 運行時判斷一個對象的類型的能力
- Python 一切皆對象,用 type,id,isinstance 獲取對象類型信息
- Inspect 模塊提供了更多獲取對象信息的函數
列表或字典推導式
- 好比 [i for i in range(10) if i % 2 == 0]
- 一種快速生成 list/dict/set 的方式。用來替代 map/filter 等
- (i for i in range(10) if i % 2 == 0) 返回生成器
Python之禪
- Tim Peters 編寫的關於 Python 編程的準則
- import this
- 編程拿不許的時候能夠參考
Python3改進
- print 成爲函數
- 編碼問題。Python3 再也不有 Unicode 對象,默認 str 就是 unicode
- 除法變化。Python3 除號返回浮點數
- 類型註解(type hint)。幫助 IDE 實現類型檢查
- 優化 super() 方便直接調用父類函數
- 高級解包操做。a, b, *rest = range(10)
- Keyword only arguments。限定關鍵字參數
- Chained exceptions。Python3 從新拋出異常不會丟失棧信息
- 一切返回迭代器 range, zip, map, dict.values, etc.are, alliterators
- 生成的 pyc 文件統一放到 __pycache__
- 一些內置庫的修改。urllib, selector 等
- 性能優化等
Python3新增
- yield from 連接字生成器
- asyncio 內置庫,async/await 原生協程支持異步編程
- 新的內置庫 enum, mock, asyncio, ipaddress, concurrent.futures 等
2/3的兼容工具
- six 模塊
- 2to3 等工具轉換代碼
- __future__
傳遞參數(一個容易混淆的問題)
- 傳遞值仍是引用呢?都不是。惟一支持的參數傳遞是共享傳參
- Call by Object(Call by Object Reference or Call by Sharing)
- Call by sharing(共享傳參)。函數形參得到實參中各個引用的副本
- 默認參數只計算一次
可變/不可變的對象
- 哪些是可變對象?哪些不可變?
- 不可變對象 bool/int/float/tuple/str/frozenset
- 可變對象 list/set/dict
- 可變對象每次賦值的時候拷貝自身的引用,而不可變對象則是建立一個新的對象
*args, **kwargs含義是什麼
- 用來處理可變參數
- *args 被打包成 tuple
- **kwargs 被打包成 dict
使用異常的常見場景
- 網絡請求(超時、鏈接錯誤等)
- 資源訪問(權限問題、資源不存在)
- 代碼邏輯(越界訪問、KeyError等)
Cpython GIL
- Cpython 解釋器的內存管理並非線程安全的
- 保護多線程狀況下對 Python 對象的訪問
- Cpython 使用簡單的鎖機制避免多個線程同時執行字節碼
GIL的影響
- 同一個時間只能有一個線程執行字節碼
- CPU 密集程序難以利用多核優點
- IO 期間會釋放 GIL,對 IO 密集程序影響不大
規避GIL影響
- CPU 密集可使用多進程 + 進程池
- IO 密集使用多線程/協程
- cython 擴展
剖析程序性能
- 二八定律,大部分時間耗時在少許代碼上
- 內置的 profile/cprofile 等工具
- 使用 pyflame(uber開源) 的火焰圖工具
服務端性能優化(Web應用通常語言不會成爲瓶頸)
- 數據結構與算法優化
- 數據庫層:索引優化,慢查詢消除,批量操做減小 IO、NoSQL
- 網絡IO:批量操做,pipeline 操做減小 IO
- 緩存:使用內存數據庫 redis/memcached
- 異步:asyncio,celery
- 併發:gevent/多線程
生成器
- 生成器就是能夠生成值的函數
- 當一個函數裏有了 yield 關鍵字就成了生成器
- 生成器能夠掛起執行而且保持當前執行的狀態
基於生成器的協程
- pep 342(Coroutines via Enhanced Generators)加強生成器功能
- 生成器能夠經過 yield 暫停執行和產出數據
- 同時支持 send() 向生成器發送數據和 throw() 向生成器拋異常
協程注意點
- 協程須要使用 send(None) 或者 next(coroutine)來預激(prime)才能啓動
- 在 yield 處協程會暫停執行
- 單獨的 yield value 會產出值給調用方
- 能夠經過 coroutine.send(value) 來給協程發送值,發送的值會賦值給 yield 表達式左邊的變量 value = yield
- 協程執行完成後(沒有遇到下一個 yield 語句)會拋出 StopIteration 異常
單元測試
- 針對程序模塊進行正確性檢驗
- 一個函數,一個類進行驗證
- 自底向上保證程序正確性
單元測試的重要性
- 保證代碼邏輯的正確性(甚至有些採用測試驅動開發(TDD))
- 單測影響設計,易測的代碼每每是高內聚低耦合的
- 迴歸測試,防止改一處整個服務不可用
單元測試庫
- nose/pytest 較爲經常使用
- mock 模塊用來模擬替換網絡請求等
- coverage 統計測試覆蓋率
歡迎關注本站公眾號,獲取更多信息