我注意到下面的代码在Python中是合法的。我的问题是为什么?有什么特别的原因吗?

n = 5
while n != 0:
    print n
    n -= 1
else:
    print "what the..."

许多初学者在尝试在while或for循环中放入if/else块时无意中发现了这种语法,并且没有正确地缩进else。解决方案是确保else块与if块对齐,假设您打算对它们进行配对。这个问题解释了为什么它没有导致语法错误,以及产生的代码意味着什么。我还得到了一个IndentationError。我该怎么解决呢?,用于报告语法错误的情况。


当前回答

我知道这是个老问题,但是…

正如Raymond Hettinger所说,应该调用while/no_break而不是while/else。 如果你看一下这个片段,我发现它很容易理解。

n = 5
while n > 0:
    print n
    n -= 1
    if n == 2:
        break
if n == 0:
    print n

现在,我们不用在while循环后检查condition,而是用else替换它,然后去掉那个检查。

n = 5
while n > 0:
    print n
    n -= 1
    if n == 2:
        break
else:  # read it as "no_break"
    print n

我总是把它读成while/no_break来理解代码,这种语法对我来说更有意义。

其他回答

thing = 'hay'
while thing:
  if thing == 'needle':
    print('I found it!!')  # wrap up for break
    break
  thing = haystack.next()
else:
  print('I did not find it.')  # wrap up for no-break

可能不幸命名为else-子句的地方是您从循环耗尽中不间断地结束的地方。

你可以没有它,如果

你中断与return或raise→调用或尝试后的整个代码是你的不可中断的地方 你在while之前设置了默认值(例如found = False) 但它可能会隐藏else子句知道要避免的错误

如果您使用带有非平凡结束符的multi-break,那么您应该在break之前使用一个简单的赋值,对no-break使用一个else子句赋值,并使用If -elif-else或match-case来避免重复非平凡的break处理代码。

注:同样适用于thing in haystack:

else子句在正常退出一个块时执行,比如击中循环条件或从try块底部掉下去。如果您中断或返回一个块,或引发异常,则不会执行。它不仅适用于while和for循环,还适用于try块。

您通常会在通常会提前退出循环的地方发现它,并且在意想不到/不寻常的情况下运行到循环的末尾。例如,如果你在一个列表中循环寻找一个值:

for value in values:
    if value == 5:
        print "Found it!"
        break
else:
    print "Nowhere to be found. :-("

请允许我举例说明为什么要使用else子句。但是:

我的观点在Leo的回答中得到了更好的解释 我使用for-而不是while-循环,但else工作类似(除非遇到break,否则执行) 有更好的方法可以做到这一点(例如,将其包装到函数中或引发异常)

打破多级循环

它是这样工作的:外部循环在结尾有一个break,所以它只会执行一次。但是,如果内部循环完成(没有找到除数),那么它将到达else语句,并且永远不会到达外部断点。这样,内部循环中的中断将跳出两个循环,而不仅仅是一个循环。

for k in [2, 3, 5, 7, 11, 13, 17, 25]:
    for m in range(2, 10):
        if k == m:
            continue
        print 'trying %s %% %s' % (k, m)
        if k % m == 0:
            print 'found a divisor: %d %% %d; breaking out of loop' % (k, m)
            break
    else:
        continue
    print 'breaking another level of loop'
    break
else:
    print 'no divisor could be found!'

我知道这是个老问题,但是…

正如Raymond Hettinger所说,应该调用while/no_break而不是while/else。 如果你看一下这个片段,我发现它很容易理解。

n = 5
while n > 0:
    print n
    n -= 1
    if n == 2:
        break
if n == 0:
    print n

现在,我们不用在while循环后检查condition,而是用else替换它,然后去掉那个检查。

n = 5
while n > 0:
    print n
    n -= 1
    if n == 2:
        break
else:  # read it as "no_break"
    print n

我总是把它读成while/no_break来理解代码,这种语法对我来说更有意义。

As far as I know the main reason for adding else to loops in any language is in cases when the iterator is not on in your control. Imagine the iterator is on a server and you just give it a signal to fetch the next 100 records of data. You want the loop to go on as long as the length of the data received is 100. If it is less, you need it to go one more times and then end it. There are many other situations where you have no control over the last iteration. Having the option to add an else in these cases makes everything much easier.