扁平化浅层嵌套列表的成语:它是如何工作的?

Mat*_*ten 6 python

我在我正在处理的模块中找到了这段代码:

l = opaque_function()
thingys = [x for y in l for x in y]
Run Code Online (Sandbox Code Playgroud)

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

>>> l = [[1,2],[3,4]]
>>> [x for y in l for x in y]
[1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)

我的眼睛想要将它解析为:[x for y in [l for x in y] ]或者[ [x for y in l] for x in y ],但是由于y没有被定义,两者都失败了.

我该怎么读这个?

(我怀疑在解释这个问题时我会感到非常尴尬.)

DSM*_*DSM 6

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

new_list = []
for y in l:
    for x in y:
        new_list.append(x)
Run Code Online (Sandbox Code Playgroud)

for y in l for x in y [do] new_list.append(x)
Run Code Online (Sandbox Code Playgroud)

[x for y in l for x in y]
Run Code Online (Sandbox Code Playgroud)


Fre*_*Foo 5

你应该读这个:

for y in l:
    for x in y:
        yield x
Run Code Online (Sandbox Code Playgroud)

那是生成器版本,但是所有的理解都有相同的基本语法:当它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]
Run Code Online (Sandbox Code Playgroud)

现在想象不得不倒退写下这整个事情:

[x if isinstance(x, int)
   for x in y
   if len(y) < 4
   for y in l]
Run Code Online (Sandbox Code Playgroud)

这对于资深的Prolog程序员来说会让人感到困惑,更不用说维护Python解析器的人了:)

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


Mar*_*ers 5

列表中显示文档:

当提供列表推导时,它由一个表达式后跟至少一个for子句和零个或多个forif子句组成.在这种情况下,新列表的元素是通过将每个forif子句视为块,从左到右嵌套,以及每次到达最内部块时评估表达式以产生列表元素而生成的元素.

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

thingys = []
for y in l:
    for x in y:
        thingys.append(x)
Run Code Online (Sandbox Code Playgroud)