列表理解
一个列表解析创建通过将表达成的每个元素的新 list 可迭代 。最基本的形式是:
[ <expression> for <element> in <iterable> ]
还有一个可选的’if’条件:
[ <expression> for <element> in <iterable> if <condition> ]
如果(可选)<condition> 评估为真, 则 <iterable> 中的每个 <element> 都插入到 <expression> 中。所有结果将在新列表中立即返回。生成器表达式是懒惰地计算的,但是列表推导会立即评估整个迭代器 - 消耗与迭代器长度成比例的内存。
要创建一个平方整数:
squares = [x * x for x in (1, 2, 3, 4)]
# squares: [1, 4, 9, 16]
for 表达式从 (1, 2, 3, 4) 依次将 x 设置为每个值。表达式 x * x 的结果附加到内部 list。内部 list 在完成时分配给变量 squares。
除了一个速度增加 (如解释在这里 ),列表理解大致相当于下面的 for 循环:
squares = []
for x in (1, 2, 3, 4):
    squares.append(x * x)
# squares: [1, 4, 9, 16]
应用于每个元素的表达式可以根据需要复杂化:
# Get a list of uppercase characters from a string
[s.upper() for s in "Hello World"]
# ['H', 'E', 'L', 'L', 'O', ' ', 'W', 'O', 'R', 'L', 'D']
# Strip off any commas from the end of strings in a list
[w.strip(',') for w in ['these,', 'words,,', 'mostly', 'have,commas,']]
# ['these', 'words', 'mostly', 'have,commas']
# Organize letters in words more reasonably - in an alphabetical order
sentence = "Beautiful is better than ugly"
["".join(sorted(word, key = lambda x: x.lower())) for word in sentence.split()]
# ['aBefiltuu', 'is', 'beertt', 'ahnt', 'gluy']
其他
else 可以在 List 理解构造中使用,但要注意语法。if / else 子句应该在 for 循环之前使用,而不是在:
# create a list of characters in apple, replacing non vowels with '*'
# Ex - 'apple' --> ['a', '*', '*', '*' ,'e']
[x for x in 'apple' if x in 'aeiou' else '*']
#SyntaxError: invalid syntax
# When using if/else together use them before the loop
[x if x in 'aeiou' else '*' for x in 'apple']
#['a', '*', '*', '*', 'e']
请注意,这使用不同的语言构造,条件表达式 ,它本身不是理解语法的一部分。而 for…in 之后的 if 是列表推导的一部分,用于从源迭代中过滤元素。
双迭代
双重迭代的顺序 [... for x in ... for y in ...] 要么是自然的,要么是反直觉的。经验法则是遵循一个等效的 for 循环:
def foo(i):
    return i, 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 inrange(3)for x infoo(i)]
就地突变和其他副作用
在使用列表推导之前,要了解通常返回 None 的副作用( 变异或 就地 函数)调用的函数与返回有趣值的函数之间的区别。
许多函数(尤其是 纯 函数)只是获取一个对象并返回一些对象。一个就地函数修改现有的对象,其被称为副作用。其他示例包括输入和输出操作,例如打印。
list.sort() 对列表进行排序 (意味着它修改了原始列表)并返回值 None。因此,它在列表理解中不会按预期工作:
[x.sort() for x in [[2, 1], [4, 3], [0, 1]]]
# [None, None, None]
相反, sorted() 返回一个已排序的 list 而不是就地排序:
[sorted(x) for x in [[2, 1], [4, 3], [0, 1]]]
# [[1, 2], [3, 4], [0, 1]]
可以使用对副作用的理解,例如 I / O 或就地功能。然而 for 循环通常更具可读性。虽然这适用于 Python 3:
[print(x) for x in (1, 2, 3)]
而是使用:
for x in (1, 2, 3):
    print(x)
在某些情况下,副作用功能是适合列表理解。 random.randrange() 具有改变随机数生成器状态的副作用,但它也返回一个有趣的值。另外,可以在迭代器上调用 next()。
以下随机值生成器不是纯粹的,但有意义,因为每次计算表达式时都会重置随机生成器:
from random import randrange
[randrange(1, 7) for _ in range(10)]
# [2, 3, 2, 1, 1, 5, 2, 4, 3, 5]
列表理解中的空白
更复杂的列表推导可能达到不期望的长度,或者变得不那么可读。虽然在示例中不太常见,但可以将列表理解分成多行,如下所示:
[
    x for x
    in 'foo'
    if x not in 'bar'
]