1. 程式人生 > Python入門教學 >17 Python 中的推導式

17 Python 中的推導式

如果需要生成一個長度為 3、內容為 0 的列表,可以使用如下的程式碼來完成這項任務:

list = [0, 0, 0]

如果需要生成一個長度為 100、內容為 0 的列表,使用如上的方式完成,需要在括號中書寫 100 個 0,既繁瑣又容易出錯,顯然是不合適的。可以使用動態的方式完成這項任務:

list = []
for i in range(100):
    list.append(0)
  • 在第 1 行,建立一個空的列表
  • 在第 2 行,建立一個迴圈語句,迴圈 100 次
  • 在第 3 行,在迴圈中,向列表新增元素 0
  • 最終,list 包含 100 個整數 0

如果需要生成一個包含 0 到 100 之間所有的偶數的列表,可以在以上的程式碼基礎上進行修改,如下所示:

list = []
for i in range(100):
    if i % 2 == 0:
        list.append(i)
  • 在第 1 行,建立一個空的列表
  • 在第 2 行,建立一個迴圈語句,迴圈 100 次
  • 在第 3 行,檢查迴圈變數 i 能否被 2 整除
  • 在第 4 行,如果變數 i 能夠被 2 整除,則表示變數 i 是偶數,將其加入到列表中
  • 最終,list 包含 0 到 100 之間的所有的偶數

在 Python 程式設計中會碰到大量的建立列表的場景,使用如上的動態新增的方式可以完成這樣的需求,但是程式碼不夠簡潔。Python 提供了列表推導的語法用於快速的構建一個列表,完成類似如下的任務:

  • 生成一個包含 100 個整數 0 的列表
  • 生成一個包含 0 到 100 之間的所有偶數的列表

類似的,Python 提供了集合推導的語法用於快速的構建一個集合,以及字典推導的語法用於快速的構建一個字典。

1. 列表推導

1.1 定義

1.1.1 定義

列表推導式對應的英文是 list comprehension,有時也被翻譯為列表解析式,是一種建立列表的簡潔語法。它的基本語法定義如下:

[expression for item iteratable]

可以認為它使用如下程式碼建立了一個 list:

list = []
for item iteratable:
    list.append(expression)
  • 在第 1 行,建立一個空的列表
  • 在第 2 行,建立一個迴圈語句,遍歷 iteratable
  • 在第 3 行,在迴圈中,向列表新增元素 expression

1.1.2 例子 1

使用列表推導生成一個包含 4 個整數 0 的列表,程式碼如下:

>>> [0 for i in range(4)]
[0, 0, 0, 0]

等價於使用 append 方法建立列表,程式碼如下:

>>> list = []
>>> for i in range(4):
...     list.append(0)
...
>>> list
[0, 0, 0, 0]

1.1.3 例子 2

使用列表推導生成一個包含 0 到 4 之間所有整數的列表,程式碼如下:

>>> [i for i in range(4)]
[0, 1, 2, 3]

等價於使用 append 方法建立列表,程式碼如下:

>>> list = []
>>> for i in range(4):
...     list.append(i)
...
>>> list
[0, 0, 0, 0]

1.2 條件語句

在基本的列表推導中,將 for 迴圈遍歷的全部元素加入到列表中,可以在 for 迴圈之後新增 if 語句用於選擇元素,它的語法定義如下:

[expression for item iteratable if condition]

可以認為它使用如下程式碼建立了一個 list:

list = []
for item iteratable:
    if condition:
        list.append(expression)

注意,在第 3 行,只有滿足條件,才會將元素新增到列表中。

使用列表推導生成一個包含 0 到 4 之間所有偶數的列表,使用 if i % 2 == 0 選擇將偶數加入到列表,程式碼如下:

>>> [i for i in range(4) if i % 2 == 0]
[0, 2]

等價於使用 append 方法建立列表,程式碼如下:

>>> list = []
>>> for i in range(4):
...     if i % 2 == 0:
...         list.append(i)
...
>>> list
[0, 2]

1.3 for 迴圈巢狀

列表推導中允許 for 迴圈巢狀,它的語法定義如下:

[expression for x in X for y in Y]

可以認為它使用如下程式碼建立了一個 list:

list = []
for x in X:
    for y in Y:
        list.append(expression)

使用列表推導生成一個包含兩個字元的字串列表,程式碼如下:

>>> [x + y for x in 'ABC' for y in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

等價於使用 append 方法建立列表,程式碼如下:

>>> list = []
>>> for x in 'ABC':
...     for y in 'XYZ':
...         list.append(x + y)
...
>>> list
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
  • 在第 1 行,建立了一個空列表
  • 在第 2 行,在外迴圈中,遍歷字串 ‘ABC’ 中的 3 個字元 ‘A’、‘B’ 和 ‘C’,迴圈變數 x 依次為’A’、‘B’ 和 ‘C’
  • 在第 3 行,在內迴圈中,遍歷字串 ‘XYZ’ 中的 3 個字元 ‘X’、‘Y’ 和 ‘Z’,迴圈變數 y 依次為’X’、‘Y’ 和 ‘Z’
  • 在第 4 行,將表示式 x + y 作為元素新增到列表中

1.4 應用舉例

  1. 初始化長度為 10 的列表
>>> [0 for i in range(10)]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  1. 將列表中的元素乘以 10
>>> list = [1, 2, 3]
>>> [i*10 for i in list]
[10, 20, 30]
  1. 將列表中所有的字串變成大寫
>>> list = ['www', 'imooc', 'com']
>>> [i.upper() for i in list]
['WWW', 'IMOOC', 'COM']
  1. 包含所有的正整數的列表
>>> list = [-1, 1, -2, 2, -3, 3]
>>> [i for i in list if i > 0]
[1, 2, 3]
  1. 初始化生成一個 M*N 的矩陣
>>> M = 2
>>> N = 3
>>> matrix = [[0 for col in range(N)] for row in range(M)]
>>> matrix
[[0,0,0], [0,0,0]]
  • 在第 1 行,設定矩陣的行數 M 為 2
  • 在第 2 行,設定矩陣的列數 N 為 3
  • 在第 3 行,生成一個 2 行 3 列的矩陣
    • [0 for col in range(N)],生成包含 3 個元素的一維向量
    • [[…] for row in range(M)],生成包含 2 個一維向量的矩陣
  1. 將矩陣平坦化
>>> matrix = [[1,2,3],[4,5,6]]
>>> matrix2 = [matrix[row][col] for row in range(2) for col in range(3)]
>>> matrix2
[1,2,3,4,5,6]
  • 在第 1 行,生成一個 2 行 3 列的矩陣
    • 矩陣的第 1 行為 [1,2,3]
    • 矩陣的第 2 行為 [4,5,6]
  • 在第 2 行,將矩陣平坦化
    • for row in range(2) 遍歷矩陣的行
    • for col in range(3) 遍歷矩陣的列
    • matrix[row][col] 獲取矩陣中指定位置的元素,將該元素放置在一個列表中
  • 在的 3 行,得到一個平坦化的列表

2. 集合推導

2.1 定義

列表推導用於快速生成一個列表,類似的,Python 同時提供了集合推導用於快速生成一個集合,語法如下:

{expression for item iteratable}

可以認為它使用如下程式碼建立了一個集合:

s = set()
for item iteratable:
    s.add(expression)
  • 在第 1 行,使用函式 set() 建立一個空的集合
  • 在第 2 行,建立一個迴圈語句,遍歷 iteratable
  • 在第 3 行,在迴圈中,向集合新增元素 expression

與列表推導類似,集合推導也支援 if 語句進行選擇,語法如下:

{expression for item iteratable if condition}

可以認為它使用如下程式碼建立了一個集合:

s = set()
for item iteratable:
    if condition:
        s.add(expression)

注意,在第 3 行,只有滿足條件,才會將元素新增到集合中。

2.2 應用舉例

  1. 包含從 0 到 10 之間所有整數的集合
>>> [i for i in range(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  1. 將集合中的元素乘以 10
>>> set = {1, 2, 3}
>>> {i*10 for i in set}
{10, 20, 30}
  1. 將列表中所有的字串變成大寫
>>> set = {'www', 'imooc', 'com'}
>>> {i.upper() for i in set}
{'WWW', 'IMOOC', 'COM'}
  1. 包含所有的正整數的集合
>>> set = {-1, 1, -2, 2, -3, 3}
>>> {i for i in list if i > 0}
{1, 2, 3}
  1. 包含兩個字元的字串集合
>>> {x + y for x in 'ABC' for y in 'XYZ'}
{'AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ'}

3. 字典推導

3.1 定義

列表推導用於快速生成一個列表,類似的,Python 同時提供了字典推導用於快速生成一個字典,語法如下:

{key:value for item iteratable}

可以認為它使用如下程式碼建立了一個字典:

dict = {}
for item iteratable:
    dict[key] = value
  • 在第 1 行,建立一個空的字典
  • 在第 2 行,建立一個迴圈語句,遍歷 iteratable
  • 在第 3 行,在迴圈中,向字典新增鍵值對

與列表推導類似,字典推導也支援 if 語句進行選擇,語法如下:

{expression for item iteratable if condition}

可以認為它使用如下程式碼建立了一個集合:

dict = {}
for item iteratable:
    if condition:
        dict[key] = value

注意,在第 3 行,只有滿足條件,才會將元素新增到字典中。

3.2 應用舉例

  1. 建立從小寫到大寫的對映
>>> list = ['www', 'imooc', 'com']
>>> {i:i.upper() for i in list}
{'www': 'WWW', 'imooc': 'IMOOC', 'com': 'COM'}
  1. 對字典進行篩選
>>> all_students = {'tom': 95, 'jerry': 80, 'mike': 99, 'john': 70}
>>> good_students = {item[0]:item[1] for item in all_students.items() if item[1] > 90}
>>> good_students
{'tom': 95, 'mike': 99}
  • 在第 1 行,建立一個包含 4 個學生的集合,姓名作為鍵,成績作為值
    • tom 的成績為 95 分
    • jerry 的成績為 80 分
    • mike 的成績為 99 分
    • john 的成績為 70 分
  • 在第 2 行,在原有的集合中選擇成績大於 90 分的學生,構造一個新的集合
    • for item in all_students.items(),遍歷 all_students
    • 迴圈變數 item 是一個包含兩個元素的元組
      • item[0] 是姓名
      • item[1] 是成績
    • if item[1] > 90,選擇成績大於 90 分
    • item[0]:item[1],使用 item[0] 作為鍵,使用 item[] 作為值
  1. 對字典進行篩選
>>> all_students = {'tom': 95, 'jerry': 80, 'mike': 99, 'john': 70}
>>> good_students = {name:grade for name,grade in all_students.items() if grade > 90}
>>> good_students
{'tom': 95, 'mike': 99}
  • 這個例子與上個例子完成相同的功能,但是使用更簡潔的語法
  • 在第 1 行,建立一個包含 4 個學生的集合,姓名作為鍵,成績作為值
    • tom 的成績為 95 分
    • jerry 的成績為 80 分
    • mike 的成績為 99 分
    • john 的成績為 70 分
  • 在第 2 行,在原有的集合中選擇成績大於 90 分的學生,構造一個新的集合
    • for name,grade in all_students.items(),遍歷 all_students
    • 迴圈變數是一個包含兩個元素的元組,‘name,grade’ 表示該元組
      • 使用變數 name 表示該元組的第 0 項
      • 使用變數 grade 表示該元組的第 1 項
    • if grade > 90,選擇成績大於 90 分
    • name:grade,使用 name 作為鍵,使用 grade 作為值

4. 小結

推導式這種方式能都快速幫我們生成我們想要的列表,集合或者字典等等。極大的加快了我們的開發速度。假如你是一位測試人員,需要大量的假資料來測試程式,這個時候推導式這種方式就很適合你。