【问题标题】:NameError in Python Nested for loops of List ComprehensionPython中的NameError嵌套用于列表理解的循环
【发布时间】:2018-09-29 06:50:05
【问题描述】:

场景:

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 从从左到右计算表达式吗? 原因,我已经用括号解决了这个问题:

[ (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]]

我只想知道这里到底发生了什么。

【问题讨论】:

  • [ j for i in range(6) for j in range(i)] 试试这个
  • 我无法确切地告诉您为什么该命令会被这样解释,但要获得开箱即用的预期行为,请使用 [ j for j in (range(i) for i in range(6))]
  • “最右边的是最外面的”。不,顺序与循环的“传统”相同。我认为您对嵌套列表理解感到困惑,例如[[j for j in range(i)] for i in range(6)]
  • @PM2Ring 是的,我很困惑。

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


【解决方案1】:

正确,它是从左到右评估的。为了添加其他人的答案,我查找了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.

【讨论】:

    【解决方案2】:

    这段代码

    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
    

    【讨论】:

    • 谢谢,所以如果我们不使用括号,最左边的 for 将被视为外循环!我不知道。
    猜你喜欢
    • 1970-01-01
    • 2014-11-18
    • 1970-01-01
    • 2015-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-07
    • 1970-01-01
    相关资源
    最近更新 更多