【问题标题】:List Comprehension - loop unrolling backwards when results collected inside list列表理解 - 当在列表中收集结果时循环向后展开
【发布时间】:2015-07-16 17:57:41
【问题描述】:

这是我之前得到答案的转贴,但我只是不清楚语法,希望有人解释发生了什么,否则我将在这里记住“规则”。

此表达式按预期工作,但将矩阵中的每个字符返回到单个列表中:

[char for line in grid for i,char in enumerate(line) if len(line[i:])>3]

如果我想让矩阵中的每个字符保留在其对应的列表(或此处的行)中,我希望下面的代码能够工作(以保留循环展开顺序,其中内循环 [理解中最右边的循环]

[[char for line in grid] for i,char in enumerate(line) if len(line[i:])>3]

这给出了一个未定义的 NameError...所以我了解到适当的结构是:

[[char for i,char in enumerate(line) if len(line[i:])>3] for line in grid]

我一直在使用推导式,我想我只是还没有遇到过这个问题,所以它让我感到意外,但似乎在推导式中创建列表需要我们从本质上反转循环顺序,现在最右边的 for语句实际上首先执行,而不是从左边执行,或者从正常的 list comp 语法反转。

我在网上和书籍中找到了几个确认语法的示例(例如,对矩阵的每个元素求平方),但它们都掩盖了这样一个事实,即当使用列表在内部累积结果时 for 循环突然反转顺序理解。

鉴于上述情况,for 语句并不总是在理解中左/右执行,这是一个公平的说法吗?

【问题讨论】:

  • 您能添加一些示例输入和预期输出吗?
  • 不,您正在外部列表推导中执行新的列表推导,在任何列表推导中,for 语句始终从左到右执行

标签: python list nested list-comprehension


【解决方案1】:

不,这是嵌套列表推导的一个实例,它是根本不同的

[char for line in grid for i,char in enumerate(line) if len(line[i:])>3]

是

的等价物
 for line in grid:
     for i,char in enumerate(line):
         if len(line[i:]) > 3:
            new_list.append(char)

你的第二个例子

[[char for i,char in enumerate(line) if len(line[i:])>3] for line in grid]

等价于

for line in grid:
    new_list.append([char for i,char in enumerate(line) if len(line[i:])>3])

在任何单个列表理解中,for 语句总是从左到右。

【讨论】:

  • 感谢 Joran 和 @Anand - 把它给 Anand 只是因为他的触摸速度更快。这些解释完全有道理,我想我今天早上需要更多的咖啡。
  • 实际上我更快 :P 但它很酷,这真的没关系 :)
  • 是的,你先发表了评论……抱歉,当我必须在多个正确答案之间进行选择时,我总是觉得很奇怪!
【解决方案2】:

推导式的语法(对于 Python 3.x)来自 documentation -

理解 ::= 表达式 comp_for

comp_for ::= "for" target_list "in" or_test [comp_iter]

comp_iter ::= comp_for | comp_if

comp_if ::= "if" expression_nocond [comp_iter]

expression 可以是任何表达式,例如文字或数学表达式或函数调用或元组或列表,甚至是另一个列表理解。表达式列表中的任何表达式here。

for 单个列表推导式中的循环总是从左到右执行,从上面的语法也可以看出。但是我们可以有嵌套的列表推导(即列表推导作为另一个列表推导的表达式,依此类推)。

当你这样做时 -

[[char for i,char in enumerate(line) if len(line[i:])>3] for line in grid]

有两个列表推导(因为您正在创建列表列表)一个用于创建外部列表的推导,一个用于创建内部列表的推导。

所以外部列表理解看起来像 -

[<inner list comprehension> for line in grid]

内部列表理解是 -

[char for i,char in enumerate(line) if len(line[i:])>3]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-30
    • 1970-01-01
    • 2022-01-12
    • 2017-05-12
    • 1970-01-01
    • 1970-01-01
    • 2021-03-20
    相关资源
    最近更新 更多