“列表理解”是什么意思? 它是如何工作的,如何使用它?

我有以下代码:

[x**2 for x in range(10)] 

当我在Python Shell中运行它时,它会返回:

 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] 

我已经search,似乎这被称为列表理解 ,但它是如何工作的?

文档

列表parsing提供了一个简洁的方式来创build列表。 常用的应用是创build新的列表,其中每个元素是应用于另一个序列的每个成员或迭代的一些操作的结果,或创build满足一定条件的那些元素的子序列。


关于你的问题,列表理解和下面的“简单”Python代码一样:

 >>> l = [] >>> for x in range(10): ... l.append(x**2) >>> l [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] 

你怎么写在一行? 嗯…我们可以…可能…使用lambda map()

 >>> list(map(lambda x: x**2, range(10))) [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] 

但是使用列表理解不是更清楚和更简单吗?

 >>> [x**2 for x in range(10)] [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] 

基本上,我们可以用x做任何事情。 不仅x**2 。 例如,运行一个x的方法:

 >>> [x.strip() for x in ('foo\n', 'bar\n', 'baz\n')] ['foo', 'bar', 'baz'] 

或者用x作为另一个函数的参数:

 >>> [int(x) for x in ('1', '2', '3')] [1, 2, 3] 

例如,我们也可以使用x作为dict对象的关键字。 让我们来看看:

 >>> d = {'foo': '10', 'bar': '20', 'baz': '30'} >>> [d[x] for x in ['foo', 'baz']] ['10', '30'] 

如何组合?

 >>> d = {'foo': '10', 'bar': '20', 'baz': '30'} >>> [int(d[x].rstrip('0')) for x in ['foo', 'baz']] [1, 3] 

等等。


你也可以在列表理解中使用ifif...else 。 例如,您只需要range(10)奇数。 你可以做:

 >>> l = [] >>> for x in range(10): ... if x%2: ... l.append(x) >>> l [1, 3, 5, 7, 9] 

啊太复杂了。 那么下面的版本呢?

 >>> [x for x in range(10) if x%2] [1, 3, 5, 7, 9] 

要使用if...else三元expression式,您需要将if ... else ...放在x之后, 而不是放在range(10)

 >>> [i if i%2 != 0 else None for i in range(10)] [None, 1, None, 3, None, 5, None, 7, None, 9] 

你听说过嵌套的列表理解吗? 你可以把两个或更多for s放在一个列表理解中 。 例如:

 >>> [i for x in [[1, 2, 3], [4, 5, 6]] for i in x] [1, 2, 3, 4, 5, 6] >>> [j for x in [[[1, 2], [3]], [[4, 5], [6]]] for i in x for j in i] [1, 2, 3, 4, 5, 6] 

让我们来谈谈第一部分, for x in [[1, 2, 3], [4, 5, 6]]中的for x in [[1, 2, 3], [4, 5, 6]]给出[1, 2, 3][4, 5, 6] 。 那么, for i in x给出了36

警告: for x in [[1, 2, 3], [4, 5, 6]]你总是需要for x in [[1, 2, 3], [4, 5, 6]] for i in x

 >>> [j for j in x for x in [[1, 2, 3], [4, 5, 6]]] Traceback (most recent call last): File "<input>", line 1, in <module> NameError: name 'x' is not defined 

我们还设置了理解词典理解生成器expression式

集合理解和列表理解基本相同,但前者返回一个集合而不是列表

 >>> {x for x in [1, 1, 2, 3, 3, 1]} {1, 2, 3} 

这是一样的:

 >>> set([i for i in [1, 1, 2, 3, 3, 1]]) {1, 2, 3} 

一个字典理解 看起来像一个集合的理解,但它使用{key: value for key, value in ...}{i: i for i in ...}而不是{i for i in ...}

例如:

 >>> {i: i**2 for i in range(5)} {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} 

它等于:

 >>> d = {} >>> for i in range(5): ... d[i] = i**2 >>> d {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} 

是否(i for i in range(5))给一个元组 ? 不!这是一个生成器expression式 。 哪个返回一个生成器

 >>> (i for i in range(5)) <generator object <genexpr> at 0x7f52703fbca8> 

这是一样的:

 >>> def gen(): ... for i in range(5): ... yield i >>> gen() <generator object gen at 0x7f5270380db0> 

你可以使用它作为一个发电机:

 >>> gen = (i for i in range(5)) >>> next(gen) 0 >>> next(gen) 1 >>> list(gen) [2, 3, 4] >>> next(gen) Traceback (most recent call last): File "<input>", line 1, in <module> StopIteration 

注意:如果你在一个函数内部使用一个列表理解,如果这个函数可以遍历一个生成器,那么你不需要[] 。 例如, sum()

 >>> sum(i**2 for i in range(5)) 30 

相关 (关于生成器): 了解Python中的生成器 。

有列表,字典和集合理解,但没有元组理解(尽pipe探索“生成器expression式”)。

他们解决了Python中传统循环是语句(不返回任何内容)而不是返回值的expression式的问题。

它们不是解决所有问题的办法,可以重写为传统的循环。 当状态需要在迭代之间保持和更新时,它们变得尴尬。

他们通常包括:

 [<output expr> <loop expr <input expr>> <optional predicate expr>] 

但是可以用许多有趣和奇怪的方式扭曲。

它们可以类似于Python中仍然存在的传统map()filter()操作,并继续使用。

如果做得好,他们的满意度很高。