为什么Python的列表理解循环顺序倒退?

jam*_*meh 12 python list-comprehension

>>> my_list = [[[[1, 2, 3], [4, 5, 6], ]]]
>>> [a for d in my_list for c in d for b in c for a in b]
[1, 2, 3, 4, 5, 6]
Run Code Online (Sandbox Code Playgroud)

相当于

>>> my_list = [[[[1, 2, 3], [4, 5, 6], ]]]
>>> new_list = []
>>> for d in my_list:
...     for c in d:
...         for b in c:
...             for a in b:
...                 new_list.append(a)
... print(new_list):
[1, 2, 3, 4, 5, 6]
Run Code Online (Sandbox Code Playgroud)

从左到右阅读时,此语法似乎倒退.根据PEP 202,"形式[... for x... for y...]嵌套,最后一个索引变化最快,就像嵌套for循环一样." 是"正确的".

看起来这个顺序(从左到右对应于外部到内部的嵌套for循环)被选中,因为这是嵌套for循环的顺序.

但是,由于列表推导的表达式部分(a在上面的例子中)对应于嵌套循环最内部的表达式(new_list.append(a)在上面的例子中),在我看来,for _ in _最接近这个表达式应该是两种情况都是一样的,即它应该是for a in b向外的:

>>> my_list = [[[[1, 2, 3], [4, 5, 6], ]]]
>>> [a for a in b for b in c for c in d for d in my_list]
NameError: name 'b' is not defined
Run Code Online (Sandbox Code Playgroud)

因此,最快变化的循环最接近动作,可以这么说.这也有助于以更加逻辑上逐步的方式从左到右阅读.

这是用户中的常见情绪吗?或者有没有人有一个很好的反驳,为什么当前的语法实现真的是"正确的"?

wim*_*wim 7

考虑:

[leaf for branch in tree for leaf in branch]
Run Code Online (Sandbox Code Playgroud)

它展开如下:

for branch in tree:
    for leaf in branch:
        yield leaf
Run Code Online (Sandbox Code Playgroud)

如果我们用另一种方式写它

[leaf for leaf in branch for branch in tree]
Run Code Online (Sandbox Code Playgroud)

在某种程度上,它可能在简单的英语中更有意义,但可能的反驳论点是,这里使用名称"branch"而不是(尚未)定义.

  • 但是,我可以对你提出相同的论点 - 即使用名称`leaf`而不是(尚未)定义.(假设我们从左到右阅读) (4认同)
  • 这正是`leaf'应该开始的原因,感谢您的比较。我仍然说模式{{leaf`:`leaf` in {`branch`:`branch` in`tree`}}比{tree中的{`leaf`:`branch`}给出了更对称,更易读的语法,例如“分支”中的“叶子”,尤其是当您有3个或更多嵌套时。 (2认同)
  • @wim“名称“branch”在尚未定义的情况下使用。”,与“leaf”不一样吗?单独的 for 理解就是这样,先使用,后声明。 (2认同)