天天看點

《編寫高品質Python代碼的59個有效方法》——第4條:用輔助函數來取代複雜的表達式

本節書摘來自華章社群《編寫高品質python代碼的59個有效方法》一書中的第4條:用輔助函數來取代複雜的表達式,作者[美]布雷特·斯拉特金(brett slatkin),更多章節内容可以通路雲栖社群“華章社群”公衆号檢視

第4條:用輔助函數來取代複雜的表達式

python的文法非常精練,很容易就能用一行表達式來實作許多邏輯。例如,要從url中解碼查詢字元串。在下例所舉的查詢字元串中,每個參數都可以表示一個整數值:

查詢字元串中的某些參數可能有多個值,某些參數可能隻有一個值,某些參數可能是空白(blank)值,還有些參數則沒有出現在查詢字元串之中。用get方法在my_values字典中查詢不同的參數時,就有可能獲得不同的傳回值。

如果待查詢的參數沒有出現在字元串中,或當該參數的值為空白時能夠傳回預設值0,那就更好了。這個邏輯看上去似乎并不值得用完整的if語句或輔助函數來實作,于是,你可能會考慮用boolean表達式。

由于python的文法非常精練,是以我們很容易就想到了這種做法。空字元串、空清單及零值,都會評估為false。是以,在下面這個例子中,如果or操作符左側的子表達式估值為false,那麼整個表達式的值就将是or操作符右側那個子表達式的值。

red那一行代碼是正确的,因為my_values字典裡确實有'red'這個鍵。該鍵所對應的值是個清單,清單中隻有一個元素,也就是字元串'5'。這個字元串會自動估值為true,是以,or表達式第一部分的值就會賦給red。

green那一行代碼也是正确的,因為get方法從my_values字典中擷取的值是個清單,該清單隻有一個元素,這個元素是個空字元串。由于空字元串會自動估值為false,是以整個or表達式的值就成了0。

opacity那一行代碼也沒有錯。my_values字典裡面沒有名為'opacity'的鍵,而當字典中沒有待查詢的鍵時,get方法會傳回第二個參數的值,是以,在本例中,get方法就會傳回僅包含一個元素的清單,那個元素是個空字元串。當字典裡沒有待查詢的'opacity'鍵時,這行代碼的執行效果與green那行代碼相同。

這樣的長表達式雖然文法正确,但卻很難閱讀,而且有時也未必完全符合要求。由于我們想在數學表達式中使用這些參數值,是以還要確定每個參數的值都是整數。為了實作這一點,我們需要把每個長表達式都包裹在内置的int函數中,以便把字元串解析為整數。

這種寫法讀起來很困難,而且看上去很亂。這樣的代碼不容易了解,初次拿到這種代碼的人,可能先要花些功夫把表達式拆解開,然後才能看明白它的作用。即使想把代碼寫得簡省一些,也沒有必要将全部内容都擠在一行裡面。

python 2.5添加了if/else條件表達式(又稱三元操作符),使我們可以把上述邏輯寫得清晰一些,同時還能保持代碼簡潔。

這種寫法比原來好了一些。對于不太複雜的情況來說,if/else條件表達式可以令代碼變得清晰。但對于上面這個例子來說,它的清晰程度還是比不上跨越多行的完整if/else語句。如果把上述邏輯全都改成下面這種形式,那我們能就感覺到:剛才那種緊縮的寫法其實挺複雜的。

現在應該把它總結成輔助函數了,如果需要頻繁使用這種邏輯,那就更應該這樣做。

調用這個輔助函數時所使用的代碼,要比使用or操作符的長表達式版本,以及使用if/else表達式的兩行版本更加清晰。

表達式如果變得比較複雜,那就應該考慮将其拆解成小塊,并把這些邏輯移入輔助函數中。這會令代碼更加易讀,它比原來那種密集的寫法更好。編寫python程式時,不要一味追求過于緊湊的寫法,那樣會寫出非常複雜的表達式。

要點

開發者很容易過度運用python的文法特性,進而寫出那種特别複雜并且難以了解的單行表達式。

請把複雜的表達式移入輔助函數之中,如果要反複使用相同的邏輯,那就更應該這麼做。

使用if/else表達式,要比用or或and這樣的boolean操作符寫成的表達式更加清晰。