Python中的NameError嵌套用于列表理解的循环

时间:2018-09-29 06:50:06

标签: python python-3.x list-comprehension nested-loops

场景:

for i in range(6):
    for j in range(i):
        j

AFAIK,在列表理解中,最右边的for是外部的,所以,我认为以下代码可以工作:

[ j for j in range(i) for i in range(6)]

但令我惊讶的是,它抛出了NameError

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'i' is not defined

我想知道为什么它不起作用。是因为python计算从 Left到Right 的表达式吗? 原因,我已经通过使用括号解决了该问题:

[ (j for j in range(i)) for i in range(6)]

输出一堆生成器表达式:

[<generator object <listcomp>.<genexpr> at 0x7f3b42200d00>, <generator object <listcomp>.<genexpr> at 0x7f3b42200d58>, <generator object <listcomp>.<genexpr> at 0x7f3b42200db0>, <generator object <listcomp>.<genexpr> at 0x7f3b42200e08>, <generator object <listcomp>.<genexpr> at 0x7f3b42200e60>, <generator object <listcomp>.<genexpr> at 0x7f3b42200eb8>]

要探索这些生成器表达式中的内容,我们可以将它们简单地转换为列表,即

[ list(j for j in range(i )) for i in range(6)]

并且输出符合预期:

[[], [0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [0, 1, 2, 3, 4]]

我只想知道这里真正发生了什么。

2 个答案:

答案 0 :(得分:4)

正确,从左到右进行评估。要添加其他人的答案,我查找了the official explanation in the documentation

  

列表推导的格式为:

 [ expression for expr in sequence1
              for expr2 in sequence2 ...
              for exprN in sequenceN
              if condition ]
  

for…in子句包含要迭代的序列。的   序列不必具有相同的长度,因为它们不是   并行迭代,但从从左向右;这是解释   在以下段落中将更加清楚。的要素   生成的列表将是表达式的连续值。决赛   if子句是可选的;如果存在,则仅对表达式求值,   如果条件为真,则添加到结果中。

     

为了使语义非常清楚,列表理解是等效的   以下Python代码:

for expr1 in sequence1:
    for expr2 in sequence2:
    ...
        for exprN in sequenceN:
             if (condition):
                  # Append the value of
                  # the expression to the
                  # resulting list.

答案 1 :(得分:0)

此代码

j for j in range(i) for i in range(6) 

就像:

for j in range(i):
    for i in range(6):
        j

外部循环在定义之前使用i,因此发生NameError,即您认为“最合适的是外部的”是错误的。

您可以使用此代码

[j for i in range(6) for j in range(i)]

以及以下代码为何起作用

[ (j for j in range(i)) for i in range(6)]
# parentheses make it work like this
for i in range(6):
     for j in range(i):
          j