列表推导式

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'
]