Python列表解析式

2021-07-25 01:09:38 字數 3946 閱讀 8303

有時候,乙個程式設計設計模式使用得十分普遍,甚至會逐步形成自己獨特的語法。python程式語言中的列表解析式(list comprehension)就是這類語法糖(syntactic sugar)的絕佳代表。

python中的 列表解析式 是個偉大的發明,但是要掌握好這個語法則有些難,因為它們並是用來解決全新的問題:只是為解決已有問題提供了新的語法。 

接下來,我們一起來學習什麼是列表解析式,以及如何掌握使用這種語法的時機。

列表解析式是將乙個列表(實際上適用於任何 可迭代物件(iterable) )轉換成另乙個列表的工具。在轉換過程中,可以指定元素必須符合一定的條件,才能新增至新的列表中,這樣每個元素都可以按需要進行轉換。 

如果你熟悉函式式程式設計(functional programming),你可以把列表解析式看作為結合了filter函式與map函式功能的語法糖: 

>>> doubled_odds = map(lambda n: n * 2, filter(lambda n: n % 2 == 1, numbers))

>>> doubled_odds = [n * 2

for n in numbers if n % 2 == 1]

如果你不熟悉函式式程式設計,也不用擔心:我稍後會通過for迴圈為大家講解。 

每個列表解析式都可以重寫為for迴圈,但不是每個for迴圈都能重寫為列表解析式。 

掌握列表解析式使用時機的關鍵,在於不斷練習識別那些看上去像列表解析式的問題(practice identifying problems that smell like list comprehensions)。

如果你能將自己的**改寫成類似下面這個for迴圈的形式,那麼你也就可以將其改寫為列表解析式: 

new_things = 

for item in old_things

:if condition_based_on(item):

你可以將上面的for迴圈改寫成這樣的列表解析式: 

new_things = ["something with " + item for item in old_things if condition_based_on(item)]

視覺化解讀聽上去是個不錯的注意,但是我們怎麼才能做到這點呢?

嘿嘿,只需要從for迴圈中複製貼上,稍微調整一下就變成了列表解析式啦。 

下面是我們複製貼上的順序:

這樣,我們將從下面這段**:

numbers = [1, 2, 3, 4, 5]

doubled_odds =

for n in numbers:

if n % 2 == 1:

轉換成了這兩行**:

numbers = [1, 2, 3, 4, 5]

doubled_odds = [n * 2 for n in numbers if n % 2 == 1]

如果是那些沒有條件子句(即if something部分)的**呢,又該怎樣複製貼上?這些形式的**甚至比有條件子句的**更好實現。 

乙個沒有if語句的for迴圈: 

doubled_numbers = 

for n in numbers:

上面這段**頁可以改寫為乙個列表解析式:

doubled_numbers = [n * 2

for n in numbers]

下面是轉換過程的詳細演示:

我們可以從上面那個簡單的for迴圈中,安裝這樣的順序複製貼上: 

那麼巢狀迴圈(nested loop)又該怎樣改寫為列表解析式呢?

下面是乙個拉平(flatten)矩陣(以列表為元素的列表)的for迴圈: 

flattened = 

for row in

matrix

:for n in

row:

下面這個列表解析式實現了相同的功能:

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

列表解析式中的巢狀迴圈讀起來就有點繞口了。

注意:我本能地會想把這個列表解析式寫成這樣:

flattened = [n for n in row for row in matrix]
但是這行**是錯誤的。這裡我不小心顛倒了兩個for迴圈的順序。正確的**是之前那個。 

如果要在列表解析式中處理巢狀迴圈,請記住for迴圈子句的順序與我們原來for迴圈的順序是一致的 。 

同樣地原則也適用集合解析式(set comprehension)和字典解析式(dictionary comprehension)。

下面的**提取單詞序列中每個單詞的首字母,建立了乙個集合(set):

first_letters = set()

forw in words

: first_letters.add(w[0])

同樣的**可以改寫為集合解析式:

first_letters =
下面的**將原有字典的鍵和值互換,從而建立了乙個新的字典:

flipped = {}

for key, value

in original.items():

flipped[value] = key

同樣的**可以改寫為字典解析式:

flipped =
你有沒有發現上面的列表解析式讀起來很困難?我經常發現,如果較長的列表解析式寫成一行**,那麼閱讀起來就非常困難。

不過,還好python支援在括號和花括號之間斷行。

斷行前:

doubled_odds = [n * 2

for n in numbers if n % 2 == 1]

斷行後:

doubled_odds = [

n * 2

for n in numbers

if n % 2 == 1

]

斷行前:

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

flattened = [

nfor row in matrix

for n in row

]

斷行前:

flipped =
斷行後:

flipped =
請注意,我們並不是隨意進行斷行:我們是在每一行複製過來的**之後斷行的。

糾結於寫不出列表解析式嗎?不要擔心。先寫乙個for迴圈,能後按照本文說的順序複製貼上,就可以寫出解析式了。 

任何類似下面**形式的for迴圈: 

new_things = 

for item in old_things

:if condition_based_on(item):

都可以被改寫為下面這種列表解析式:

new_things = ["something with " + item for item in old_things if condition_based_on(item)]

python 列表解析式

python的列表解析式只是為了解決已有問題提供新的語法 什麼是列表解析式?列表解析式是將乙個列表轉換成另乙個列表的工具。在轉換過程中,可以指定元素必須符合一定的條件,才能新增至新的列表中,這樣每個元素都可以按需要進行轉換。可以把列表解析式看作為結合了filter函式與map函式功能的語法糖 dou...

Python列表解析(列表推導式)

列表解析 用來動態地建立列表 expr for iter var in iterable if cond expr 例子一 map lambda x x 2,range 6 0,1,4,9,16,25 x 2 for x in range 6 0,1,4,9,16,25 列表解析式可以取代內建的ma...

Python學習筆記 列表解析式

python列表解析式是個很神奇的東西!在列表中運用了for迴圈,或者for迴圈加上if 等條件判斷語句,能夠很明顯的簡化 量。1.單個for迴圈 a i for i in range 1,4 a 1,2,3 2.兩個for迴圈 a x,y for x in range 1,4 for y in r...