天天看點

Python 知識點: 清單推導式(list comprehension)

Python 知識點: 清單推導式(list comprehension)
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:
        evens.append(i)
           

很明顯,for循環占用了4行代碼,而 list comprehension 隻用了1行代碼。

文章開始說到推導式的文法規範時,我們講了if表達式是可有可無的,這也符合我們程式設計遇到的實際情況。比如,要生成一個10以内的整數的平方的清單:

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

複雜的嵌套循環

我們先來看一個例子,把一個矩陣(以清單為元素的清單)展平為一個清單。首先,我們用for循環來實作一下:

matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
]

flattened = []

for row in matrix:
    for i in row:
        flattened.append(i)
           

接着我們用清單推導式實作該功能:

flattened = [i for row in matrix for i in row]
           

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

推導式的可讀性

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

面對一行長長的代碼該如何下口讀,如何了解呢?别着急,好在

允許在中括号、花括号之間斷行:

清單推導式的斷行:

斷行前:

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

斷行後:

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

帶嵌套循環的推導式的斷行:

flattened = [i for row in matrix for i in row]

flattened = [
    i
    for row in matrix
    for i in row
]
           

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

前面我們也提到過,推導式不僅僅适用于清單,它同樣使用于字典dict和集合set。

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

changed = {value: key for key, value in input_dict.items()}
用```  
一個清單的所有單詞的首字母生成一個集合:
           

chars = {w[0] for w in words_list}

`

過以上講解就可以輕松掌握Python的清單推導式(list comprehension)了,簡而言之,就是把普通的多行for循環壓縮成一行代碼,這種壓縮文法适用于清單、字典、集合等可疊代資料結構(iterables)。

有關Python技術文章優先釋出在我的個人部落格:猿人學

公衆号:猿人學Pyhton