python list comprehension double for
1 2 3 4 | vec = [[1,2,3], [4,5,6], [7,8,9]] print [num for elem in vec for num in elem] <----- this >>> [1, 2, 3, 4, 5, 6, 7, 8, 9] |
这是在骗我。我知道Elem是来自
Python如何解释这个问题?它的顺序是什么?
让我们把它分解。
简单的列表理解:
1 | [x for x in collection] |
如果我们把它分成几个部分,这很容易理解:
A 是结果列表中的项目。B 是集合C 中的每个项目。C 是集合本身。
这样,我们可以写:
1 | [x.lower() for x in words] |
以便将列表中的所有单词转换为小写。
当我们用类似这样的另一个列表来复杂化这一点时:
1 | [x for y in collection for x in y] # [A for B in C for D in E] |
在这里,发生了一些特殊的事情。我们希望最终的清单包括
A 是结果列表中的项目。B 是集合C 中的每个项目。C 是集合本身D 是集合E 中的每一项(在这种情况下,也是A 中的每一项)E 是另一个集合(在本例中,B )
此逻辑类似于正常for循环:
1 2 3 | 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 |
为了扩展这一点,并给出一个很好的例子+解释,假设有一列火车。
火车引擎(前部)总是在那里(列表理解的结果)
那么,有多少节车厢,每节车厢的形式是:
列表理解可能如下所示:
1 | [z for b in a for c in b for d in c ... for z in y] |
这就像是有一个规则的for循环:
1 2 3 4 5 6 | for b in a: for c in b: for d in c: ... for z in y: # have z |
换言之,在列表理解中,您不需要沿着一行缩进,而是在末尾添加下一个循环。
回到火车类比:
尾巴是什么?在清单理解中,尾部是一个特殊的东西。您不需要一个,但是如果您有一个尾部,尾部是一个条件,请看这个例子:
1 | [line for line in file if not line.startswith('#')] |
只要文件中的每一行没有以hashtag开头(
使用列车"尾部"的诀窍是,在您拥有所有循环的最终"引擎"或"结果"的同时,检查其是否正确/错误,上面规则for循环中的示例如下:
1 2 3 | for line in file: if not line.startswith('#'): # have line |
请注意:尽管在我对火车的类比中,在火车的尾部只有一个"尾部",但条件或"尾部"可以在每一个"车厢"或回路之后…
例如:
1 2 3 | >>> 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循环中:
1 2 3 4 5 6 7 8 9 10 11 | >>> for y in z: if sum(y)>10: for x in y: if x < 10: print x 5 6 7 8 9 |
从列表理解文档中:
When a list comprehension is supplied, it consists of a single expression followed by at least one
for clause and zero or morefor orif clauses. In this case, the elements of the new list are those that would be produced by considering each of the for or if clauses a block, nesting from left to right, and evaluating the expression to produce a list element each time the innermost block is reached.
换句话说,假设
1 2 3 | for elem in vec: for num in elem: num # the *single expression* from the spec |
其中,列表理解将使用最后一个最里面的块作为结果列表的值。
您的代码等于:
1 2 3 4 | temp = [] for elem in vec: for num in elem: temp.append(num) |