列表推導式

Python中的列表推導是非常簡潔的語法結構,它通過將函式應用於列表中的每個元素,可用於從其他列表生成列表。以下部分解釋並演示了這些表示式的用法。

列表推導通過施加一個表示式到的可迭代的每個元素來建立一個新的列表,最基本的形式是:

[ <expression> for <element> in <iterable> ]

還有一個可選的if條件:

[ <expression> for <element> in <iterable> if <condition> ]

如果(可選的)條件是真的話,那在迭代物件中的每個元素都會執行一遍表示式<expression>。所有結果將在新列表中立即返回。Python中的生成器表示式是懶惰地計算的,但是列表推導會立即施加到整個迭代器,它消耗與迭代器長度成比例的記憶體。

假如你要建立一個list平方整數:

squares = [x * x for x in (1, 2, 3, 4)]
# squares: [1, 4, 9, 16]

for表示式一次設定x(1, 2, 3, 4)中的每個值。表示式的結果x * x附加到內部列表。完成後,內部列表將分配給變數squares

除了一個速度增加(解釋在這裡),列表理解大致相當於下面的for迴圈:

squares = []
for x in (1, 2, 3, 4):
    squares.append(x * x)
# squares: [1, 4, 9, 16]

列表推導式中的else

else可以在列表推導式中使用,但要注意其語法。if...else判斷是在for迴圈之前使用,而不是在以下之後:

# 建立一個含有`apple`的字元序列,替換其中的非母音字母為 `*`
# 比如 - 'apple' --> ['a', '*', '*', '*' ,'e']

[x for x in 'apple' if x in 'aeiou' else '*']
# SyntaxError: invalid syntax

# 使用if/else對時,它們應該在for的前面
[x if x in 'aeiou' else '*' for x in 'apple']
#['a', '*', '*', '*', 'e']

雙迭代

雙重迭代的順序[... for x in ... for y in ...]是理解起來是自然或反直覺的。經驗法則是遵循等效for迴圈:

def foo(i):
    return i + 0.5

for i in range(3):
    for x in foo(i):
        yield str(x)

這變為:

[str(x)
    for i in range(3)
        for x in foo(i)
]

這可以壓縮成一行 [str(x) for i in range(3) for x in foo(i)]

提示

跟一般的for雙迴圈相比,只需要把最裡層的表示式放在最前面寫,就能夠實現正確的列表表示式雙迭代了。

列表推導式中的空白符

更復雜的列表推導可能需要很長的長度,這降低了程式碼的可讀性,所以你可以增加空白字元或者換行來提高可讀性,方便理解。

[
    x for x
    in 'foo'
    if x not in 'bar'
]