Python清单理解

示例

列表理解list通过将表达式应用于可迭代的每个元素来创建新的列表。最基本的形式是:

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

还有一个可选的“如果”条件:

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

每个<element>在<iterable>已插入到<expression>如果(可选的)<condition>评估为true。所有结果将立即返回到新列表中。生成器表达式的计算是延迟的,但是列表推导会立即评估整个迭代器-消耗的内存与迭代器的长度成正比。

要创建list平方整数:

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

的for表达式设置x,以依次从每个值(1, 2, 3, 4)。表达式的结果x * x被附加到一个internal list。完成后,将内部list变量分配给变量squares。

除了提高速度(如此处所述)外,列表理解还大致等同于以下for循环:

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

应用于每个元素的表达式可以根据需要复杂:

# 从字符串获取大写字符列表
[s.upper() for s in "Hello World"]
# ['你好,世界']

# 从列表中的字符串末尾去除所有逗号
[w.strip(',') for w in ['these,', 'words,,', 'mostly', 'have,commas,']]
# [“这些”,“单词”,“大部分”,“有逗号”]

# 以字母顺序更合理地组织单词中的字母
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循环之前使用,而不要在循环之后使用:

# 在苹果中创建字符列表,用“ *”代替非元音
# Ex - 'apple' --> ['a', '*', '*', '*' ,'e']

[x for x in 'apple' if x in 'aeiou' else '*']
#SyntaxError:语法无效

# 当同时使用if / else时,请在循环前使用它们
[x if x in 'aeiou' else '*' for x in 'apple']
#['a','*','*','*','e']

请注意,这使用了一种不同的语言构造,即条件表达式,它本身不是理解语法的一部分。而ifafterfor…in 列表理解的一部分,用于从可迭代的源中筛选元素。


双重迭代

两次迭代的顺序[... 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 in range(3) for x in foo(i)]


就地突变和其他副作用

在使用列表推导之前,请了解通常会返回的函数(其副作用为mutating就地函数)None与返回有趣值的函数之间的区别。

许多函数(尤其是函数)仅获取一个对象并返回某个对象。一个就地函数修改现有的对象,其被称为副作用。其他示例包括输入和输出操作,例如打印。

list.sort()就地对列表进行排序(意味着它会修改原始列表)并返回value None。因此,它在列表理解中将无法正常工作:

[x.sort() for x in [[2, 1], [4, 3], [0, 1]]]
# [无,无,无]

而是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,1,5,2,4,3,5]


列表推导中的空白

更复杂的列表理解可能会达到不希望的长度,或者变得难以理解。尽管在示例中不太常见,但可以将列表理解分为多行,如下所示:

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