本節書摘來自華章社群《編寫高品質python代碼的59個有效方法》一書中的第8條:不要使用含有兩個以上表達式的清單推導,作者[美]布雷特·斯拉特金(brett slatkin),更多章節内容可以通路雲栖社群“華章社群”公衆号檢視
第8條:不要使用含有兩個以上表達式的清單推導
除了基本的用法(參見本書第7條)之外,清單推導也支援多重循環。例如,要把矩陣(也就是包含清單的清單,即二維清單)簡化成一維清單,使原來的每個單元格都成為新清單中的普通元素。這個功能采用包含兩個for表達式的清單推導即可實作,這些for表達式會按照從左至右的順序來評估。
上面這個例子簡單易懂,這就是多重循環的合理用法。還有一種包含多重循環的合理用法,那就是根據輸入清單來建立有兩層深度的新清單。例如,我們要對二維矩陣中的每個單元格取平方,然後用這些平方值建構新的矩陣。由于要多使用一對中括号,是以實作該功能的代碼會比上例稍微複雜一點,但是依然不難了解。
如果表達式裡還有一層循環,那麼清單推導就會變得很長,這時必須把它分成多行來寫,才能看得清楚一些。
可以看出,此時的清單推導并沒有比普通的寫法更加簡潔。于是,筆者改用普通的循環語句來實作相同的效果。由于循環語句帶有适當的縮進,是以看上去要比清單推導更清晰。
清單推導也支援多個if條件。處在同一循環級别中的多項條件,彼此之間預設形成and表達式。例如,要從數字清單中選出大于4的偶數,那麼下面這兩種清單推導方式是等效的。
每一級循環的for表達式後面都可以指定條件。例如,要從原矩陣中把那些本身能為3所整除,且其所在行的各元素之和又大于等于10的單元格挑出來。我們隻需編寫很簡短的代碼,就可用清單推導來實作此功能,但是,這樣的代碼非常難懂。
盡管這個例子稍微有點複雜,但在實際程式設計中,确實會出現這種看上去似乎适合用清單推導來實作的情況。筆者強烈建議大家盡量不要編寫這種包含複雜式子的清單推導。這樣會使其他人很難了解這段代碼。這麼寫雖然能省下幾行空間,但卻會給稍後閱讀代碼的人帶來很大障礙。
在清單推導中,最好不要使用兩個以上的表達式。可以使用兩個條件、兩個循環或一個條件搭配一個循環。如果要寫的代碼比這還複雜,那就應該使用普通的if和for語句,并編寫輔助函數(參見本書第16條)。
要點
清單推導支援多級循環,每一級循環也支援多項條件。
超過兩個表達式的清單推導是很難了解的,應該盡量避免。