我理解这种结构是如何运作的:

for i in range(10):
    print(i)

    if i == 9:
        print("Too big - I'm giving up!")
        break
else:
    print("Completed successfully")

但我不明白为什么在这里使用else作为关键字,因为它表明有问题的代码只在for块未完成时运行,这与它所做的相反!无论我怎么想,我的大脑都不能从for语句无缝地过渡到else语句块。对我来说,continue和continuouswith更有意义(我正试着训练自己这样读它)。

我想知道Python程序员是如何在头脑中(或者大声地,如果你喜欢)阅读这个结构的。也许我遗漏了一些可以使这些代码块更容易破译的东西?


这个问题是关于底层设计决策的,也就是说,为什么能够编写这些代码是有用的。另请参阅Python while语句中的Else子句,了解语法含义的具体问题。


当前回答

简单来说,你可以这样想;

如果它在for循环中遇到break命令,else部分将不会被调用。 如果在for循环中没有遇到break命令,则调用else部分。

换句话说,如果for循环迭代没有被break“打断”,else部分将被调用。

其他回答

我同意,它更像是一个'elif not[条件(s)提高中断]'。

我知道这是一个老话题,但我现在正在研究同样的问题,我不确定是否有人能以我理解的方式抓住这个问题的答案。

对我来说,有三种方法来“阅读”For…else or While…所有等价的Else语句是:

Else ==如果循环正常完成(没有中断或错误) Else ==如果循环没有遇到断点 Else == Else not(条件引发中断)(假设存在这样的条件,否则就不会有循环)

因此,从本质上讲,循环中的“else”实际上是一个“elif…”,其中'…’表示(1)不中断,相当于(2)NOT[条件(s)引发中断]。

我认为关键在于,如果没有break, else是没有意义的,所以for…其他的包括:

for:
    do stuff
    conditional break # implied by else
else not break:
    do more stuff

a的基本元素。else循环如下所示,你可以用更简单的英语阅读它们:

for:
    do stuff
    condition:
        break
else: # read as "else not break" or "else not condition"
    do more stuff

正如其他帖子所说,当你能够找到你的循环正在寻找的东西时,通常会引发一个break,所以else:变成了“如果目标物品没有找到,该怎么办”。

例子

您还可以同时使用异常处理、中断和for循环。

for x in range(0,3):
    print("x: {}".format(x))
    if x == 2:
        try:
            raise AssertionError("ASSERTION ERROR: x is {}".format(x))
        except:
            print(AssertionError("ASSERTION ERROR: x is {}".format(x)))
            break
else:
    print("X loop complete without error")

结果

x: 0
x: 1
x: 2
ASSERTION ERROR: x is 2
----------
# loop not completed (hit break), so else didn't run

例子

一个简单的例子,断点被击中。

for y in range(0,3):
    print("y: {}".format(y))
    if y == 2: # will be executed
        print("BREAK: y is {}\n----------".format(y))
        break
else: # not executed because break is hit
    print("y_loop completed without break----------\n")

结果

y: 0
y: 1
y: 2
BREAK: y is 2
----------
# loop not completed (hit break), so else didn't run

例子

没有中断的简单示例,没有引发中断的条件,也没有遇到错误。

for z in range(0,3):
     print("z: {}".format(z))
     if z == 4: # will not be executed
         print("BREAK: z is {}\n".format(y))
         break
     if z == 4: # will not be executed
         raise AssertionError("ASSERTION ERROR: x is {}".format(x))
else:
     print("z_loop complete without break or error\n----------\n")

结果

z: 0
z: 1
z: 2
z_loop complete without break or error
----------

Raymond Hettinger做了一个非常棒的演讲,题为“将代码转换成美丽的、地道的Python”,在演讲中他简要地介绍了for Python的历史。其他结构。相关部分是“在循环中区分多个出口点”,从15:50开始,持续约3分钟。以下是要点:

for…else构造是由Donald Knuth设计的,作为某些GOTO用例的替代; 重用else关键字是有意义的,因为“它是Knuth使用的,人们知道,在那个时候,所有的(for语句)都在下面嵌入了一个if和GOTO,他们期望else;” 事后看来,它应该被称为“nobreak”(或者可能是“nobreak”),这样就不会让人困惑了

所以,如果问题是“为什么他们不改变这个关键字?”,那么Cat Plus Plus可能会给出最准确的答案——在这一点上,它对现有代码的破坏性太大了,不太实用。但如果你真正想问的问题是为什么其他东西一开始就被重用,嗯,显然这在当时看起来是个好主意。

就我个人而言,我喜欢折衷的注释# no break in-line,因为else可能会被误认为属于循环内部。它相当清晰简洁。Bjorn在他的回答结尾链接的摘要中简要提到了这个选项:

为了完整起见,我应该提一下 语法,想要这个语法的程序员现在就可以拥有它: 项目顺序如下: 过程(项目) Else: #不休息 套件


*视频中那部分的额外引用:“就像我们调用lambda makefunction一样,没有人会问,‘lambda是做什么的?’”

很好的回答是:

这就解释了历史,而且 这就赋予了 引用以简化您的翻译/理解。

我在这里的注释来自Donald Knuth曾经说过(抱歉找不到参考),有一个结构,其中while-else与if-else无法区分,即(在Python中):

x = 2
while x > 3:
    print("foo")
    break
else:
    print("boo")

具有相同的流程(不包括低级别差异):

x = 2
if x > 3:
    print("foo")
else:
    print("boo")

关键是if-else可以被认为是while-else的语法糖,它在if块的末尾有隐含的break。相反的含义是,while循环是if的扩展,更常见(它只是重复/循环的条件检查),因为if经常在while之前教授。然而,这不是真的,因为这将意味着else块在while-else每次当condition为false时执行。

为了便于理解,可以这样想:

没有break, return等,循环只在condition不再为真时结束,在这种情况下else块也将执行一次。在Python for的情况下,你必须考虑c风格的for循环(带条件)或将它们转换为while。

另注:

循环中的过早中断、返回等使得condition不可能变为false,因为当condition为true时,执行跳出了循环,并且它永远不会再回来检查它。

一个循环的else分支只执行一次,不管这个循环是否进入它的循环体,除非循环体已经进入但没有结束。也就是说,在循环中会遇到break或return语句。

my_list = []
for i in my_list:
    print(i, end=',')
else:
    print('loop did not enter')

##################################    

for i in range(1,6,1):
    print(i, end=',')
else:
    print('loop completed successfully:', i)

##################################    

for i in range(1,6,1):
    if i == 3:
        print('loop did not finish:', i)
        break
    print(i, end=',')
else:
    print('else:', i)

输出:

loop did not enter
1,2,3,4,5,loop completed successfully: 5
1,2,loop did not finish: 3

while-else也是一样的。

import random
random.seed(8)

i = 100
while i < 90:
    print(i, end=',')
    i = random.randint(0,100)
else:
    print('loop did not enter:', i)

##################################    

i = 25
while i < 90:
    print(i, end=',')
    i = random.randint(0,100)
else:
    print('loop completed successfully:', i)

##################################    

i = 25
while i < 90:
    if i % 10 == 0:
        print('loop did not finish:', i)
        break
    print(i, end=',')
    i = random.randint(0,100)
else:
    print('else:', i)

输出:

loop did not enter: 100
25,29,47,48,16,24,loop completed successfully: 90
25,5,loop did not finish: 10

else语句块中的代码将在for循环未被打破时执行。

for x in xrange(1,5):
    if x == 5:
        print 'find 5'
        break
else:
    print 'can not find 5!'
#can not find 5!

来自文档:break和continue语句,以及循环中的else子句

Loop statements may have an else clause; it is executed when the loop terminates through exhaustion of the list (with for) or when the condition becomes false (with while), but not when the loop is terminated by a break statement. This is exemplified by the following loop, which searches for prime numbers: >>> for n in range(2, 10): ... for x in range(2, n): ... if n % x == 0: ... print(n, 'equals', x, '*', n//x) ... break ... else: ... # loop fell through without finding a factor ... print(n, 'is a prime number') ... 2 is a prime number 3 is a prime number 4 equals 2 * 2 5 is a prime number 6 equals 2 * 3 7 is a prime number 8 equals 2 * 4 9 equals 3 * 3 (Yes, this is the correct code. Look closely: the else clause belongs to the for loop, not the if statement.) When used with a loop, the else clause has more in common with the else clause of a try statement than it does that of if statements: a try statement’s else clause runs when no exception occurs, and a loop’s else clause runs when no break occurs. For more on the try statement and exceptions, see Handling Exceptions. The continue statement, also borrowed from C, continues with the next iteration of the loop: >>> for num in range(2, 10): ... if num % 2 == 0: ... print("Found an even number", num) ... continue ... print("Found a number", num) Found an even number 2 Found a number 3 Found an even number 4 Found a number 5 Found an even number 6 Found a number 7 Found an even number 8 Found a number 9