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 應用舉例
- 初始化長度為 10 的列表
>>> [0 for i in range(10)]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
- 將列表中的元素乘以 10
>>> list = [1, 2, 3]
>>> [i*10 for i in list]
[10, 20, 30]
- 將列表中所有的字串變成大寫
>>> list = ['www', 'imooc', 'com']
>>> [i.upper() for i in list]
['WWW', 'IMOOC', 'COM']
- 包含所有的正整數的列表
>>> list = [-1, 1, -2, 2, -3, 3]
>>> [i for i in list if i > 0]
[1, 2, 3]
- 初始化生成一個 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 個一維向量的矩陣
- 將矩陣平坦化
>>> 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 應用舉例
- 包含從 0 到 10 之間所有整數的集合
>>> [i for i in range(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
- 將集合中的元素乘以 10
>>> set = {1, 2, 3}
>>> {i*10 for i in set}
{10, 20, 30}
- 將列表中所有的字串變成大寫
>>> set = {'www', 'imooc', 'com'}
>>> {i.upper() for i in set}
{'WWW', 'IMOOC', 'COM'}
- 包含所有的正整數的集合
>>> set = {-1, 1, -2, 2, -3, 3}
>>> {i for i in list if i > 0}
{1, 2, 3}
- 包含兩個字元的字串集合
>>> {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 應用舉例
- 建立從小寫到大寫的對映
>>> list = ['www', 'imooc', 'com']
>>> {i:i.upper() for i in list}
{'www': 'WWW', 'imooc': 'IMOOC', 'com': 'COM'}
- 對字典進行篩選
>>> 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[] 作為值
- 對字典進行篩選
>>> 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. 小結
推導式這種方式能都快速幫我們生成我們想要的列表,集合或者字典等等。極大的加快了我們的開發速度。假如你是一位測試人員,需要大量的假資料來測試程式,這個時候推導式這種方式就很適合你。