python中的列表推導式

2021-10-21 20:15:58 字數 3300 閱讀 8060

python裡面有個很棒的語法糖(syntactic sugar),它就是list comprehension,有人把它翻譯成「列表推導式」,也有人翻譯成「列表解析式」。名字聽上去很難理解,但是看它的語法就很清晰了。雖然名字叫做 list comprehension,但是這個語法同樣適用於dict、set等這一系列可迭代(iterable)資料結構。

語法規範:

out_list = [out_express for out_express in input_list if out_express_condition]

其中的if條件判斷根據需要可有可無。

下面看乙個具體的例子,生成乙個包含10以內的偶數的list:

in [1]: evens = [i for i in range(10) if i % 2 == 0]

in [2]: evens

out[2]: [0, 2, 4, 6, 8]

由for迴圈公升級到列表推導式:

在沒有了解list comprehension之前,上面那個生成偶數list的通常做法是用for迴圈:

evens = 

for i in range(10):

if i % 2 == 0:

很明顯,for迴圈占用了4行**,而list comprehension只用了1行**。

squares = [i**2 for i in range(10)]

複雜的巢狀迴圈

我們先來看乙個例子,把乙個矩陣(以列表為元素的列表)展平為乙個列表。首先,我們用for迴圈來實現一下:

接著我們用列表推導式實現該功能:

flattened = [i for row in matrix for i in row]
另外,以上所看到的列表推導式都只有乙個迴圈,實際上它可使用多個迴圈,就像巢狀迴圈一樣。例如如下**:

d_list = [(x, y) for x in range(5) for y in range(4)]

# d_list列表包含20個元素

print(d_list)

上面**中,x 是遍歷 range(5) 的迭代變數(計數器),因此該 x 可迭代 5 次;y 是遍歷 range(4) 的計數器,因此該 y 可迭代 4 次。因此,該(x,y)表示式一共會迭代 20 次。上面的 for 表示式相當於如下巢狀迴圈:

dd_list =

for x in range(5):

for y in range(4):

執行上面**,可以看到如下輸出結果:

[(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3), (3, 0), (3, 1), (3, 2), (3, 3), (4, 0), (4, 1), (4, 2), (4, 3)]

當然,也支援類似於三層巢狀的 for 表示式,例如如下**:

e_list = [[x, y, z] for x in range(5) for y in range(4) for z in range(6)]

# e_list列表包含120個元素

print(e_list)

對於包含多個迴圈的 for 表示式,同樣可指定 if 條件。假如我們有乙個需求:程式要將兩個列表中的數值按「能否整除」的關係配對在一起。比如 src_a 列表中包含 30,src_b 列表中包含 5,其中 30 可以整除 5,那麼就將 30 和 5 配對在一起。對於上面的需求使用 for 表示式來實現非常簡單,例如如下**:

src_a = [30, 12, 66, 34, 39, 78, 36, 57, 121]

src_b = [3, 5, 7, 11]

# 只要y能整除x,就將它們配對在一起

result = [(x, y) for x in src_b for y in src_a if y % x == 0]

print(result)

執行上面**,可以看到如下輸出結果:

[(3, 30), (3, 12), (3, 66), (3, 39), (3, 78), (3, 36), (3, 57), (5, 30), (11, 66), (11, 121)]

還是一行**就搞定,但一行裡面有兩個for,看起來很亂,兩個for,哪個在前哪個在後呢?只要記住他們的順序和不用推導式的原始for迴圈是一致的即可。

推導式的可讀性

一行**搞定幾行**的事情,看上去很簡潔,但是讀起來很費勁,尤其是當條件語句很長的時候,把這一行**變得很長,超過了**規範規定的長度(一般是80個字元),也使得理解**變得困難。

面對一行長長的**該如何下口讀,如何理解呢?別著急,好在python允許在中括號、花括號之間斷行:

列表推導式的斷行:

斷行前:

evens = [i for i in range(10) if i % 2 == 0]
斷行後:

evens = [

ifor i in range(10)

if i % 2 == 0

]

帶巢狀迴圈的推導式的斷行:

斷行前:

flattened = [i for row in matrix for i in row]
斷行後:

flattened = [

ifor row in matrix

for i in row

]

字典(dict)和集合(set)的推導式:

前面我們也提到過,推導式不僅僅適用於列表,它同樣使用於字典dict和集合set。

把乙個字典的key和value互換:

changed =
用乙個列表的所有單詞的首字母生成乙個集合:

chars =
通過以上講解就可以輕鬆掌握python的列表推導式(list comprehension)了,簡而言之,就是把普通的多行for迴圈壓縮成一行**,這種壓縮語法適用於列表、字典、集合等可迭代資料結構(iterables)。

Python中列表推導式

理解 舊的列表通過相應的邏輯生成新的列表。列表推導式 格式 表示式 for 變數 in 舊列表 或者 表示式 for 變數 in 舊列表 if 條件 過濾掉長度小於或者等於3的人名。names tom jason jack ha hey lilala result name for name in ...

python中的列表推導式

類似於這樣 x for x in range 101 x for x in range 10 if x 2 0 x y for x in range 10 for y in range 10 式子,就叫做列表推導式 列表推導式的好處就是能快速生成列表 列表推導式的好處就是浪費記憶體 空間複雜度太大 ...

python中的列表推導式

所謂的列表推導式,就是指的輕量級迴圈建立列表。建立乙個0 10的列表 a x for x in range 11 print a 輸出結果 0,1,2,3,4,5,6,7,8,9 上面的列表推導式等價於下面,只是 非常簡化。a for x in range 10 建立乙個1 10之間偶數的列表 a ...