python高級編程之列表推導式


1. 一個簡單的例子

在Python中,如果我們想修改列表中所有元素的值,可以使用 for 循環語句來實現。

例如,將一個列表中的每個元素都替換為它的平方:

>>> L = [1, 2, 3, 4, 5] >>> for i in range(len(L)): ... L[i] = L[i] ** 2 >>> L [1, 4, 9, 16, 25] 

另一種優雅的實現方式就是使用列表推導式(List Comprehensions):

>>> L = [1, 2, 3, 4, 5] >>> L = [x ** 2 for x in L] >>> L [1, 4, 9, 16, 25] 

2. 基本語法

我們具體來分析上面給出的例子

>>> L = [x ** 2 for x in L] 

我們將列表推導式寫在一個方括號內,因為它最終構建的是一個列表。

列表推導式主要由兩部分構成:

  • 循環變量表達式( x ** 2
  • for 循環頭部( for x in L )

是不是非常簡單!

3. 工作原理

Python在執行列表推導式時,會對可迭代對象 L 進行迭代,將每一次迭代的值賦給循環變量 x ,然后收集變量表達式 x ** 2 的計算結果,最終由這些結果構成了新的列表,也就是列表推導式所返回的值。

只要支持 for 循環進行迭代的對象,都可以對它使用列表推導式。

例如,我們將一個字符串進行移位處理:

>>> S = 'abcde' >>> S = ''.join([chr(ord(c)+1) for c in S]) >>> S 'bcdef' 

4. 高級語法

除了像上面介紹的 [x ** 2 for x in L] 這種基本語法之外,列表推導式還有一些高級的擴展。

4.1. 帶有if語句

我們可以在 for 語句后面跟上一個 if 判斷語句,用於過濾掉那些不滿足條件的結果項。

例如,我想去除列表中所有的偶數項,保留奇數項,可以這么寫:

>>> L = [1, 2, 3, 4, 5, 6] >>> L = [x for x in L if x % 2 != 0] >>> L [1, 3, 5] 

4.2. 帶有for嵌套

在復雜一點的列表推導式中,可以嵌套有多個 for 語句。按照從左至右的順序,分別是外層循環到內層循環。

例如:

>>> [x + y for x in 'ab' for y in 'jk'] ['aj', 'ak', 'bj', 'bk'] 

4.3. 既有if語句又有for嵌套

列表推導式可以帶任意數量的嵌套 for 循環,並且每一個 for 循環后面都有可選的 if 語句。

通用語法:

[ expression for x in X [if condition] for y in Y [if condition] ... for n in N [if condition] ] 

例如,下面的代碼輸出了0~4之間的偶數和奇數的組合。

>>> [(x, y) for x in range(5) if x % 2 == 0 for y in range(5) if y % 2 == 1] [(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)] 

等價於下面的一般 for 循環:

>>> L = [] >>> for x in range(5): ... if x % 2 == 0: ... for y in range(5): ... if y % 2 == 1: ... L.append((x, y)) >>> L [(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)] 

4.4. 列表推導式生成矩陣

生成矩陣的方式有多種,例如手動賦值、一般for循環,還有就是列表推導式。如果我們要用列表推導式生成下面的矩陣,可以怎么寫?

>>> M = [[1, 2, 3], ... [4, 5, 6], ... [7, 8, 9]] 

一種方法是:

>>> M = [[x, x+1, x+2] for x in [1, 4, 7]] >>> M [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 

矩陣的列數少時可以使用這種方法。

如果矩陣的列數較多,我們可以使用另外一種方式:在循環變量的表達式中使用列表推導式。

具體代碼如下:

>>> M = [[y for y in range(x, x+3)] for x in [1, 4, 7]] >>> M [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 

與之前帶 for 嵌套的語法不同,這個例子中,實際使用的是最基本的 [expression for x in L] 語法,只有一個 for 語句。

復雜的地方在於前面的變量表達式 expression 不再是簡單的變量運算,而是一個列表推導式,在這個例子中就是 [y for y in range(x, x+3)] 。
內層的列表推導式返回一個行向量,而這些行向量經由外層的列表推導式,最終形成一個二維列表,也就是我們想要的矩陣。

當然,在實際的應用中不能單純追求代碼的簡潔,還要考慮到代碼的可讀性和維護成本。
如果代碼變得過於復雜,不易於理解,我們寧可多寫幾行代碼來增加它的可讀性。

5. 生成器表達式

生成器表達式與列表推導式的語法相同,區別在於生成器表達式的外面使用圓括號,而列表推導式使用方括號。

有關生成器的介紹,請參考這篇文章:《Python高級編程之初識生成器》

6. 集合推導式和字典推導式

注意:集合推導式和字典推導式只有在Python2.7以及之后的版本中才有,Python2.7之前的版本不支持這兩種推導式。

集合推導式的語法與列表推導式相同,只需要把外面的方括號改成花括號即可。

例如,我們可以通過以下方式來生成一個集合:

>>> {x ** 2 for x in [1, 2, 2]} {1, 4} 

字典推導式的外面也是使用花括號,不過花括號的內部需要包含鍵值兩部分。

在值不重復的情況下,我們可以通過字典推導式快速交換鍵值對:

>>> D = {'a':1, 'b':2, 'c':3} >>> D = {value: key for key, value in D.items()} >>> D {1: 'a', 2: 'b', 3: 'c'}


總結:在編寫或是閱讀這類推導式的時候,一定要注意先從for..in開始,最后再看前面的循環變量表達式。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM