一、函數參數與返回值基礎知識
1、不要使用可變類型(list等)作為參數默認值,用None
來代替。
參數默認值只會在函數定義階段被創建一次,之后無論創建多少次,函數內拿到的默認值都是同一個對象,為規避這個問題,一般會用None來代替可變默認類型對象。
2、使用標記對象,可以嚴格區分函數調用時是否提供了某個參數。
所謂標記對象,是專門定義一個獨一無二的變量類型,當用戶調用函數確實沒有傳遞某個參數時、默認值會變成這個標記對象,那么我們就可以知道服務到底有沒有傳這個變量了、而不是僅僅通過None來判斷。
3、定義僅限關鍵字參數,可以強制要求調用方提供參數名,提升可讀性。
4、函數應當擁有穩定的返回類型,不要返回多種類型。
5、適合返回None
的情況——操作類函數、查詢類型函數中表示意料之外的缺失值。
6、在執行失敗時,相比返回None
,直接拋出異常更合適。
7、如果提前返回結果可以提升可讀性,就提前返回,不要去追求所謂的“單一出口”。
二、代碼可維護性技巧
1、不要編寫太長的函數,雖然長度沒有強制標準,但65行是一個危險的信號。
2、圈復雜度是評估函數復雜程度的常用指標,一般超過10的函數都需要重構。
3、抽象與分層思想可以幫助我們更好地構建與管理復雜的系統。
4、同一個函數內的代碼應該處于同一抽象級別。
簡單來說,按照職能、數據流、業務流進行分級分類,逐一遞進,然后做模塊和函數的抽象與劃分,不要一股腦都寫在一起。
比方說通過頁面查詢后端數據,就可以分解成接口View層、請求處理與參數校驗層,以及數據查詢抽象Data層。
三、函數與狀態
1、沒有副作用的無狀態純函數比較易于理解、維護,但大多數時候“狀態”不可避免。
2、避免使用全局變量給函數增加狀態。
3、當函數狀態較為簡單時,可以使用閉包技巧。
所謂閉包技巧,就是在函數內再定義一個函數,而后使用nonlocal來對外層函數的狀態記錄變量進行更新,舉例:
def counter():value = 0def _counter():# nonlocal 用來標注變量來自上層作用域,如果不標明,內層函數將無法直接的修改外層函數變量nonlocal valuevalue += 1return valuereturn _counter> c = counter()
> c()
1
> c()
2
> c2 = counter()
> c2()
1
4、當函數需要較為復雜的狀態管理時,建議定義類來管理狀態。
四、語言機制對函數的影響
1、functools.partial()
可以用來快速構建偏函數。
2、functools.lru_cache()
可以用來給函數添加緩存。
3、比起map
和filter
,列表推導式的可讀性更強。
4、lambda
函數知識一種語法糖,可以使用operator
模塊等方式來替代它。
5、Python語言里的遞歸限制較多,可以的話,請盡量使用循環來替代。
參考內容:《Python工匠——案例、技巧與工程實踐》