6

我在我正在处理的模块中发现了这段代码:

l = opaque_function()
thingys = [x for y in l for x in y]

我看不懂这个。通过实验,我能够确定它正在展平一个 2 级嵌套列表,但语法对我来说仍然是不透明的。它显然省略了一些可选的括号。

>>> l = [[1,2],[3,4]]
>>> [x for y in l for x in y]
[1, 2, 3, 4]

我的眼睛想将其解析为:[x for y in [l for x in y] ][ [x for y in l] for x in y ],但由于y未定义,这两个都失败了。

我应该怎么读这个?

(我怀疑当这被解释时我会感到非常尴尬。)

4

4 回答 4

6

这曾经让我很困惑。您应该像嵌套循环一样阅读它:

new_list = []
for y in l:
    for x in y:
        new_list.append(x)

变成

for y in l for x in y [do] new_list.append(x)

变成

[x for y in l for x in y]
于 2012-09-25T15:10:12.480 回答
5

您应该将其阅读为:

for y in l:
    for x in y:
        yield x

那是生成器版本,但所有推导式都具有相同的基本语法:虽然x放在前面,但表达式的其余部分仍然是从左到右读取的。一开始我也对此感到困惑,以为它会反过来,但是一旦添加了过滤表达式,它就有意义了:

>>> l = [[1,2,3,4,5], [1,"foo","bar"], [2,3]]
>>> [x for y in l
...    if len(y) < 4
...    for x in y
...    if isinstance(x, int)]
[1, 2, 3]

现在想象一下必须把整个事情倒过来写:

[x if isinstance(x, int)
   for x in y
   if len(y) < 4
   for y in l]

即使是资深的 Prolog 程序员也会感到困惑,更不用说维护 Python 解析器的人了 :)

当前的语法也与Haskell中的相匹配,这首先激发了列表推导。

于 2012-09-25T15:10:40.870 回答
5

列表中显示文档:

提供列表推导时,它由一个表达式组成,后跟至少一个for子句和零个或多个fororif子句。在这种情况下,新列表的元素是通过将每个fororif子句视为一个块、从左到右嵌套并在每次到达最里面的块时计算表达式以产生一个列表元素而产生的元素。

因此,您的表达式可以重写为:

thingys = []
for y in l:
    for x in y:
        thingys.append(x)
于 2012-09-25T15:15:35.183 回答
1
lis=[x for y in l for x in y] is Equivalent to:


lis=[]
for y in l:
   for x in y:
      lis.append(x)
于 2012-09-25T15:10:30.337 回答