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

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

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


当前回答

如果while循环没有中断,则执行Else。

我有点喜欢用“跑步者”来比喻。

“else”就像越过终点线,与你是从赛道的起点还是终点出发无关。"else"只有当你在两者之间的某个地方中断时才不会执行。

runner_at = 0 # or 10 makes no difference, if unlucky_sector is not 0-10
unlucky_sector = 6
while runner_at < 10:
    print("Runner at: ", runner_at)
    if runner_at == unlucky_sector:
        print("Runner fell and broke his foot. Will not reach finish.")
        break
    runner_at += 1
else:
    print("Runner has finished the race!") # Not executed if runner broke his foot.

主要的用例是使用这种打破嵌套循环,或者如果你想只在循环没有在某处中断时运行某些语句(认为中断是一种不寻常的情况)。

例如,下面是一个关于如何在不使用变量或try/catch的情况下跳出内部循环的机制:

for i in [1,2,3]:
    for j in ['a', 'unlucky', 'c']:
        print(i, j)
        if j == 'unlucky':
            break
    else: 
        continue  # Only executed if inner loop didn't break.
    break         # This is only reached if inner loop 'breaked' out since continue didn't run. 

print("Finished")
# 1 a
# 1 b
# Finished

其他回答

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

正如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来理解代码,这种语法对我来说更有意义。

在Python中,'while: else:'结构的更好用法应该是,如果'while'中没有执行循环,则执行'else'语句。今天它的工作方式没有意义,因为您可以使用下面的代码获得相同的结果……

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

我的回答将集中在我们什么时候可以使用while/for-else。

乍一看,使用时似乎没有什么不同

while CONDITION:
    EXPRESSIONS
print 'ELSE'
print 'The next statement'

and

while CONDITION:
    EXPRESSIONS
else:
    print 'ELSE'
print 'The next statement'

因为打印'ELSE'语句似乎总是在这两种情况下执行(当while循环结束或不运行时)。

然后,只有当打印'ELSE'语句不被执行时,情况才有所不同。 它是在while下面的代码块中有一个突破

In [17]: i = 0

In [18]: while i < 5:
    print i
    if i == 2:
        break
    i = i +1
else:
    print 'ELSE'
print 'The next statement'
   ....:
0
1
2
The next statement

如与:

In [19]: i = 0

In [20]: while i < 5:
    print i
    if i == 2:
        break
    i = i +1
print 'ELSE'
print 'The next statement'
   ....:
0
1
2
ELSE
The next statement

Return不在此类别中,因为它对上述两种情况具有相同的效果。

异常引发也不会造成差异,因为当它引发时,下一个代码将在异常处理程序中执行(block除外),else子句或while子句后面的代码将不会被执行。

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:

如果while循环没有中断,则执行Else。

我有点喜欢用“跑步者”来比喻。

“else”就像越过终点线,与你是从赛道的起点还是终点出发无关。"else"只有当你在两者之间的某个地方中断时才不会执行。

runner_at = 0 # or 10 makes no difference, if unlucky_sector is not 0-10
unlucky_sector = 6
while runner_at < 10:
    print("Runner at: ", runner_at)
    if runner_at == unlucky_sector:
        print("Runner fell and broke his foot. Will not reach finish.")
        break
    runner_at += 1
else:
    print("Runner has finished the race!") # Not executed if runner broke his foot.

主要的用例是使用这种打破嵌套循环,或者如果你想只在循环没有在某处中断时运行某些语句(认为中断是一种不寻常的情况)。

例如,下面是一个关于如何在不使用变量或try/catch的情况下跳出内部循环的机制:

for i in [1,2,3]:
    for j in ['a', 'unlucky', 'c']:
        print(i, j)
        if j == 'unlucky':
            break
    else: 
        continue  # Only executed if inner loop didn't break.
    break         # This is only reached if inner loop 'breaked' out since continue didn't run. 

print("Finished")
# 1 a
# 1 b
# Finished