让我们分解一下。
一个简单的列表理解:
[x for x in collection]
如果我们把它分成几个部分,这就很容易理解了:[A for B in C]
-
A
是结果列表中的项目
-
B
是集合中的每一项C
-
C
是集合本身。
这样,就可以写出:
[x.lower() for x in words]
为了将列表中的所有单词转换为小写。
当我们用另一个列表将其复杂化时,如下所示:
[x for y in collection for x in y] # [A for B in C for D in E]
在这里,发生了一些特别的事情。我们希望我们的最终清单包括A
物品,以及A
里面发现了物品B
项目,所以我们必须告诉列表理解。
-
A
是结果列表中的项目
-
B
是集合中的每一项C
-
C
是集合本身
-
D
是集合中的每一项E
(在这种情况下,也A
)
-
E
是另一个集合(在本例中,B
)
这个逻辑类似于普通的 for 循环:
for y in collection: # for B in C:
for x in y: # for D in E: (in this case: for A in B)
# receive x # # receive A
为了扩展这一点,并给出一个很好的例子+解释,想象有一列火车。
火车引擎(前面)总是在那里(列表理解的结果)
那么,有任意数量的火车车厢,每节火车车厢的形式为:for x in y
列表理解可能如下所示:
[z for b in a for c in b for d in c ... for z in y]
这就像有这个常规的 for 循环:
for b in a:
for c in b:
for d in c:
...
for z in y:
# have z
换句话说,在列表理解中,您只需将下一个循环添加到末尾,而不是向下一行并缩进。
回到火车的比喻:
Engine
- Car
- Car
- Car
... Tail
尾巴是什么?尾部在列表推导式中是一个特殊的东西。你不need一个,但是如果有尾巴,尾巴就是一个条件,看这个例子:
[line for line in file if not line.startswith('#')]
这将为您提供文件中的每一行,只要该行不以主题标签开头(#
),其他的就跳过了。
使用火车“尾部”的技巧是,当您从所有循环中获得最终“引擎”或“结果”时,会同时检查它的真/假,上面的示例是常规 for 循环看起来像这样:
for line in file:
if not line.startswith('#'):
# have line
请注意:虽然在我对火车的类比中,火车的末端只有一个“尾巴”,但条件或“尾巴”可以在every“汽车”或循环...
例如:
>>> z = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
>>> [x for y in z if sum(y)>10 for x in y if x < 10]
[5, 6, 7, 8, 9]
在常规 for 循环中:
>>> for y in z:
if sum(y)>10:
for x in y:
if x < 10:
print x
5
6
7
8
9