为什么 python 在 for 和 while 循环之后使用“else”?

Why does python use 'else' after for and while loops?

提问人:Kent Boogaart 提问时间:4/3/2012 最后编辑:Karl KnechtelKent Boogaart 更新时间:7/28/2023 访问量:303396

问:

我了解这个结构是如何工作的:

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

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

但我不明白为什么在这里用作关键字,因为它表明有问题的代码只有在块未完成时才会运行,这与它的作用相反!无论我怎么想,我的大脑都无法从陈述无缝推进到块。对我来说,或者会更有意义(我正在努力训练自己这样阅读它)。elseforforelsecontinuecontinuewith

我想知道 Python 编码人员是如何在脑海中阅读这个结构的(或者大声朗读,如果你愿意的话)。也许我错过了一些可以使此类代码块更容易破译的东西?


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

python if-statement for-loop for-else

评论

51赞 Marcin 4/3/2012
你可能想在脑海中把它翻译成“然后”。
112赞 Daniel Roseman 4/3/2012
别忘了 Python 禅宗中的关键台词:“......除非你是荷兰人,否则这种方式一开始可能并不明显。
94赞 MestreLion 5/23/2013
在我的脑海中,我把它翻译成“如果不是打破”。而且,由于在“我找到了它”循环中经常使用,您可以将其翻译为“如果未找到”,这与阅读的内容相去不远breakelse
44赞 Sam Kauffman 8/21/2014
我认为许多人在这里遇到的真正问题是“在 for 循环之后放置和放置之间有什么区别?答案是,只有当循环包含 a 时,它们的行为才会有所不同(如下所述)。for ... else foo()foo()break
7赞 Les 3/10/2021
在提出这个问题将近 10 年后,在使用 Python 编程 3 年后,这是我第一次看到“for-else”、“while-else”结构。我希望它的低频使用进一步减少到蒸发。世界上到处都是初级程序员,他们会“取消缩进”“else”以“修复”他们发现的错误。

答:

46赞 Cat Plus Plus 4/3/2012 #1

因为他们不想在语言中引入新的关键字。每个标识符都会窃取一个标识符并导致向后兼容性问题,因此通常是最后的手段。

评论

5赞 Ponkadoodle 1/12/2014
在这种情况下,似乎是一个更好的选择。在引入此构造时,finally 关键字是否尚未存在?finally
46赞 Cat Plus Plus 1/12/2014
@Wallacoloo也好不到哪里去,因为它意味着块总是在循环之后执行,而事实并非如此(因为如果只是在循环之后运行代码,那将是多余的)。finally
9赞 Air 5/16/2014
@pepr子句执行不受 (docs测试代码) 的影响elsecontinue)
1赞 Den-Jason 9/8/2020
completed这里本来是一个更好的关键词;表示 for 循环的执行没有被破坏(无论是否实际执行了任何循环)。至少这样,如果有人不小心移动了缩进,它最终不会导致不正确的行为,因为 突然移动到了一个构造......elseif
1赞 Anm 10/19/2023
最好的关键字是类似 ,但当然关键字应该是一个单数词,所以不确定关键字应该是什么。afterBreak
14赞 pcalcao 4/3/2012 #2

我读了这样的话:

如果仍然有条件运行循环,请做一些事情,否则做其他事情。

评论

0赞 Wolf 11/28/2014
你的条件是有帮助的(+1),虽然这是错误的 - 这是人类;-)
1赞 Mark Amery 2/16/2018
-1;/ 的这个发音听起来像是 the will always run after the loop,但事实并非如此。for:else:else:
0赞 jamylak 4/3/2012 #3

你可以把它想象成,就像在其余的东西中一样,或者其他的东西,不是在循环中完成的。else

397赞 Stand with Gaza 4/3/2012 #4

即使对于经验丰富的 Python 编码人员来说,这也是一个奇怪的结构。当与 for 循环结合使用时,它基本上意味着“在可迭代对象中找到一些项目,否则如果没有找到,请执行......”。如:

found_obj = None
for obj in objects:
    if obj.key == search_key:
        found_obj = obj
        break
else:
    print('No object found.')

但是,每当您看到此构造时,更好的选择是将搜索封装在函数中:

def find_obj(search_key):
    for obj in objects:
        if obj.key == search_key:
            return obj

或者使用列表推导式:

matching_objs = [o for o in objects if o.key == search_key]
if matching_objs:
    print('Found {}'.format(matching_objs[0]))
else:
    print('No object found.')

它在语义上不等同于其他两个版本,但在非性能关键代码中工作得足够好,在这些代码中,是否迭代整个列表并不重要。其他人可能不同意,但我个人会避免在生产代码中使用 for-else 或 while-else 块。

参见 [Python-ideas] Summary of for...else 线程

评论

74赞 agf 4/3/2012
列表推导是错误的单行。如果你正在寻找一个项目,如循环示例中所示,并且想要使用生成器表达式/列表推导式,那么你希望或将其包装在 / 中,并且不使用默认值而不是 / 。fornext((o for o in objects if o.key == search_key), None)tryexceptifelse
5赞 andrean 3/11/2014
就像 Lance Helsten 的回答一样,在实际情况下,最好使用构造。for/else
7赞 maxywb 5/3/2014
干杯。我有一个缩进严重的文件,其中 an 与 a 配对,我不知道这是合法的。elsefor
27赞 dhackner 8/28/2014
值得一提的是,即使 for 循环有值,else 子句也会运行,除非语句是显式运行的,如本例所示。从上面的文档中可以看出:“该子句还有另一个感知问题:如果循环中没有,则该子句在功能上是多余的。例如:breakelsebreakelsefor x in [1, 2, 3]:\n print x\n else:\n print 'this executes due to no break'
4赞 aaa90210 7/4/2019
“”在可迭代对象中找到一些项目,否则如果没有找到,请执行......”这是错误的。我们迭代的原因很多,而不是“发现东西”。
876赞 Lance Helsten 4/3/2012 #5

一个常见的构造是运行一个循环,直到找到某些东西,然后跳出循环。问题是,如果我跳出循环或循环结束,我需要确定发生了哪种情况。一种方法是创建一个标志或存储变量,让我进行第二次测试以查看循环是如何退出的。

例如,假设我需要搜索列表并处理每个项目,直到找到标志项目,然后停止处理。如果缺少标志项,则需要引发异常。

使用 Python ...构建你有forelse

for i in mylist:
    if i == theflag:
        break
    process(i)
else:
    raise ValueError("List argument missing terminal flag.")

将此与不使用此句法糖的方法进行比较:

flagfound = False
for i in mylist:
    if i == theflag:
        flagfound = True
        break
    process(i)

if not flagfound:
    raise ValueError("List argument missing terminal flag.")

在第一种情况下,它与它使用的 for 循环紧密绑定。在第二种情况下,绑定不那么牢固,并且在维护过程中可能会引入错误。raise

评论

65赞 boatcoder 2/2/2015
我不得不说,这种句法糖可能会腐蚀你的项目的牙齿。这不会成为一本书。Python: the good parts
6赞 Lance Helsten 3/11/2015
process将对 之前存在于列表中的每个元素执行,之后不会对列表中的元素执行,也不会在 上执行。itheflagtheflagtheflag
20赞 Lost Crotchet 5/2/2019
如果可迭代对象没有元素,则也会执行 else 语句
2赞 Robo Robok 9/10/2020
我认为他们犯了一个错误,称之为.这真的具有误导性。在尝试它之前,我很确定它会在没有元素要迭代的情况下运行。更准确的名称应该是 ,或者其他什么。else:passed:completed:
4赞 Les 3/10/2021
至于维护,把 “for-else” 放到一个 “if” 块中,看看你的维护者是否不止一次地将 “else” 缩进到“if”上,认为他们正在修复一个错误。
24赞 Ayan 5/13/2014 #6

我认为文档对其他有很好的解释,继续

[...]当循环因列表穷尽而终止时 (with for) 或当条件变为 false (with while) 时,它会执行,但当循环因 break 语句终止时不会执行。

来源:Python 2 文档:控制流教程

263赞 Air 5/20/2014 #7

Raymond Hettinger 做了一个精彩的演讲,题为 Transforming Code into Beautiful, Idiomatic Python,他在演讲中简要介绍了该构造的历史。相关部分是“区分循环中的多个出口点”,从 15:50 开始,持续约三分钟。以下是要点:for ... else

  • 该结构是由 Donald Knuth 设计的,用于替代某些用例;for ... elseGOTO
  • 重用这个关键词是有道理的,因为“这是 Knuth 使用的,人们知道,当时,所有的 [语句] 都嵌入了 和 下面,他们希望elseforifGOTOelse;"
  • 事后看来,它应该被称为“no break”(或者可能是“nobreak”),这样就不会混淆了。

因此,如果问题是“他们为什么不更改这个关键字?”那么 Cat Plus Plus 可能给出了最准确的答案——在这一点上,它对现有代码的破坏性太大而无法实用。但是,如果你真正要问的问题是为什么一开始就被重用了,那么,显然这在当时似乎是个好主意。else

就我个人而言,我喜欢在可能被误认为属于循环内部的地方进行内联评论的折衷方案。它相当清晰和简洁。这个选项在 Bjorn 在回答末尾链接的摘要中得到了简要提及:# no breakelse

为了完整起见,我应该提到这一点,但略有变化 语法,想要这种语法的程序员现在可以拥有它:

for item in sequence:
    process(item)
else:  # no break
    suite

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

评论

3赞 jaaq 10/28/2020
为什么不在 else 旁边添加对 nobreak 的支持,让两者相等并并存,并制定一个明确的 PEP 风格规则,即应该使用 nobreak 而不是 else?
2赞 Air 11/17/2020
@jaaq我不能代表 Python 核心开发人员,但请考虑 PEP 20 的一句话:“应该有一种——最好只有一种——显而易见的方法来做到这一点。
3赞 jaaq 12/9/2020
最近的 PEP 文档指出,多种方式是可以的,只是不是多种明显的方式。由于关键字可能明显,也许这确实是改进语法的一种方式。nobreak
7赞 zwol 7/13/2021
“nobreak”将是一个新关键字,通常,语言设计人员对向现有语言添加关键字非常犹豫,因为它会破坏所有将该标识符用于其他内容的代码。
2赞 Jann Poppinga 8/31/2021
虽然这个例子是不完整的,因为没有 .for ... elsebreak
7赞 0xc0de 7/7/2014 #8

我把它读成“当 完全耗尽,并且执行即将在完成 之后进入下一个语句时,else 子句将被执行。因此,当迭代被 中断时,这将不会被执行。iterableforbreak

26赞 Neil_UK 2/5/2015 #9

我发现“获取”for/else 的作用,更重要的是,何时使用它的最简单方法是专注于 break 语句跳转到的位置。For/else 构造是一个块。中断跳出块,因此跳到“else子句上”。如果 else 子句的内容只是跟在 for 子句后面,它永远不会被跳过,因此必须通过将其放在 if 中来提供等效的逻辑。这之前已经说过了,但并不完全是这些话,所以它可能会帮助其他人。尝试运行以下代码片段。为了清楚起见,我全心全意地赞成“不间断”的评论。

for a in range(3):
    print(a)
    if a==4: # change value to force break or not
        break
else: #no break  +10 for whoever thought of this decoration
    print('for completed OK')

print('statement after for loop')

编辑 - 我注意到这个问题仍在运行

第二个更好的想法......

“不间断”评论是否定的。理解一个肯定的断言要容易得多,那就是可迭代对象已经用尽了。for

for a in range(3):
    print(a)
    if a==4: # change value to force break or not
        print('ending for loop with a break')
        break
else: # when iterable exhausted  
    print('ending for loop as iterable exhausted')

print('for loop ended one way or another')

这也强化了这种解释

if iterable_supplies_a_value:
    run_the_for_with_that_value
else:
    do_something_else

评论

2赞 Mark Amery 2/16/2018
“break 跳出块,因此跳到'over'else 子句上”——虽然这可能有助于“获取”/,但它并没有真正为关键字 be 提供理由。鉴于这里给出的框架,似乎会更自然。(被选中是有原因的,在其他答案中给出 - 只是这里没有提供。for:else:elsethen:else
0赞 Beni Cherniavsky-Paskin 10/19/2023
@Neil_UK “if iterable_supplies_a_value:”听起来像“else:”,仅在可迭代对象为空时运行,这是对它的作用的常见错误猜测。但是你答案的前几部分正确地解释了它。正如所写的,不清楚你说的“这也加强了这种解释”是什么意思
6赞 NotAnAmbiTurner 1/7/2016 #10

我同意,这更像是一个“elif not [条件提高休息]”。

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

对我来说,有三种方式可以“阅读”in或语句,它们都是等价的,是:elseFor... elseWhile... else

  1. else == if the loop completes normally (without a break or error)
  2. else == if the loop does not encounter a break
  3. else == else not (condition raising break)(大概有这样的条件,否则你不会有循环)

因此,从本质上讲,循环中的“else”实际上是一个“elif ...”其中“...”是 (1) 无中断,相当于 (2) 不是 [条件提高中断]。

我认为关键是没有“中断”是没有意义的,所以包括:elsefor...else

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

因此,循环的基本要素如下,您可以用更通俗易懂的英语将它们读作:for...else

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

正如其他海报所说,当你能够找到你的循环正在寻找的东西时,通常会提出中断,所以变成了“如果找不到目标项目该怎么办”。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
----------
18赞 3rdWorldCitizen 1/13/2016 #11

由于技术部分已经得到了很好的回答,我的评论只是与产生这个回收关键字的混淆有关。

由于 Python 是一种非常有说服力的编程语言,因此误用关键字更为臭名昭著。这个关键词完美地描述了决策树流程的一部分,“如果你不能做这个,(否则)做那个”。这是用我们自己的语言暗示的。else

相反,将此关键字与 and 语句一起使用会导致混淆。原因是,我们作为程序员的职业生涯告诉我们,语句存在于决策树中;它的逻辑作用域一个有条件地返回要遵循的路径的包装器。同时,循环语句有一个比喻性的明确目标,即达到某种目的。在过程的不断迭代后,目标才得以实现。whileforelse

if / else 指示要遵循的路径。循环遵循路径,直到“目标”完成

问题在于,这是一个明确定义条件中最后一个选项的词。该词的语义由 Python 和 Human Language 共享。但是人类语言中的“else”这个词从来不用于表示某人或某事在某事完成后将采取的行动。如果在完成过程中出现问题(更像是中断语句),将使用它。else

最后,关键字将保留在 Python 中。很明显,这是错误的,当每个程序员都试图想出一个故事来理解它的用法时,就像一些助记符一样。如果他们选择了关键字,我会很高兴.我相信这个关键词完全适合这个迭代流程,即循环后的回报then

它类似于某个孩子在组装玩具的每一步后遇到的情况:然后呢,爸爸?

评论

0赞 Spacen Jasset 3/31/2018
我认为这个答案解决了我认为 OP 正在谈论的混乱问题。else 关键字的作用与你对 else 的英文含义的期望完全相反,当附加到 for 的动作时。从理论上讲,对于...else 的工作方式可能有所不同,因为当循环中断时,您最终会进入 else 部分,但问题是要使用它来查找元素 x,并处理找不到 x 的情况,您可能必须在整体之后使用标志或其他测试。else 构造
0赞 Jürgen A. Erhard 10/21/2023
我作为程序员的职业生涯没有教会我任何这种东西。即使我的职业是程序员,这仍然是事实。
5赞 GoingMyWay 8/26/2016 #12

语句块中的代码将在循环未中断时执行。elsefor

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 语句,以及循环上的 Clauses

循环语句可能有一个 else 子句;当循环因列表穷尽而终止时 (with for) 或当条件变为 false (with while) 时,将执行它,但当循环因 break 语句终止时不执行。以下循环就是例证,该循环搜索质数:

>>> 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

(是的,这是正确的代码。仔细观察:else 子句属于 for 循环,而不是 if 语句。

当与循环一起使用时,else 子句与 try 语句的 else 子句的共同点比 if 语句的共同点更多:try 语句的 else 子句在未发生异常时运行,循环的 else 子句在未发生中断时运行。有关 try 语句和异常的详细信息,请参阅处理异常。

continue 语句(也是从 C 语言借来的)继续进行循环的下一次迭代:

>>> 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

评论

1赞 Air 1/24/2017
这没有增加任何内容,也没有回答问题,这不是如何,而是为什么
6赞 cizixs 4/27/2017 #13

关键字在这里可能会令人困惑,正如许多人所指出的那样,像这样的东西更合适。elsenobreaknotbreak

为了从逻辑上理解,将其与 ,而不是 进行比较,大多数 python 程序员都熟悉以下代码:for ... else ...try...except...elseif...else...

try:
    do_something()
except:
    print("Error happened.") # The try block threw an exception
else:
    print("Everything is find.") # The try block does things just find.

同样,可以将其视为一种特殊的:breakException

for x in iterable:
    do_something(x)
except break:
    pass # Implied by Python's loop semantics
else:
    print('no break encountered')  # No break statement was encountered

区别是隐含的,你不能把它写出来,所以它变成了:pythonexcept break

for x in iterable:
    do_something(x)
else:
    print('no break encountered')  # No break statement was encountered

是的,我知道这种比较可能很困难和令人厌烦,但它确实澄清了混乱。

评论

2赞 godaygo 10/31/2017
从资源复制时,您应该创建一个指向资源的链接:Nick Coghlan 的 Python Notes
1赞 cizixs 11/1/2017
@godaygo感谢您的链接。我在第一次学习 python 时阅读并接受了这个概念,在写答案时没有记住来源。
3赞 Mark Amery 2/16/2018
@cizixs 你“没有记住来源”,只是碰巧包含了与原文相同的整句评论?噢
0赞 Phil 8/22/2020
我来这里找这个,但是..其实不和?try: stuff(); except: error(); else: ok()try: stuff(); ok(); except: error()
0赞 user19513069 10/8/2022
@phil 不完全是,因为如果内部提出了一个异常,它就会冒泡。else
69赞 Ad Infinitum 10/27/2017 #14

为了简单起见,你可以这样想;

  • 如果在循环中遇到该命令,则不会调用该部件。breakforelse
  • 如果在循环中没有遇到该命令,则将调用该部件。breakforelse

换言之,如果 for 循环迭代没有 “中断” ,则该部分将被调用。breakelse

评论

4赞 Amal K 10/2/2019
如果循环的主体引发异常,则也不会执行该块。else
13赞 Chiraz BenAbdelkader 7/5/2020
如果列表为空并且 for 循环根本不迭代,else 块也会被执行。
4赞 timgeb 2/18/2022
如果喜欢读作 .for/elsefor/nobreak
2赞 Harley 11/12/2022
@Amal K 中,如果使用 try-except 处理异常,else 仍会执行
2赞 Jonathan Sudiaman 3/2/2018 #15

这是除了搜索之外的另一个惯用用例。假设您想等待条件为真,例如在远程服务器上打开端口,以及一些超时。然后,您可以使用如下结构:while...else

import socket
import time

sock = socket.socket()
timeout = time.time() + 15
while time.time() < timeout:
    if sock.connect_ex(('127.0.0.1', 80)) is 0:
        print('Port is open now!')
        break
    print('Still waiting...')
else:
    raise TimeoutError()
3赞 Wizard 8/25/2018 #16
for i in range(3):
    print(i)

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

这里的“否则”非常简单,只是卑鄙

1、“如果完成”for clause

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

    if i == 2:
        print("Too big - I'm giving up!")
        break;
if "for clause is completed":
    print("Completed successfully")

写“for clause is completed”这样的长语句是很有用的,所以他们引入了“else”。

else这是一个 if 的本质。

2、但是,怎么样for clause is not run at all

In [331]: for i in range(0):
     ...:     print(i)
     ...: 
     ...:     if i == 9:
     ...:         print("Too big - I'm giving up!")
     ...:         break
     ...: else:
     ...:     print("Completed successfully")
     ...:     
Completed successfully

所以它完全是逻辑组合:

if "for clause is completed" or "not run at all":
     do else stuff

或者这样说:

if "for clause is not partially run":
    do else stuff

或者这样:

if "for clause not encounter a break":
    do else stuff

评论

0赞 Wizard 8/25/2018
else 在 SQL 中充当“事务”。
2赞 Germaine Goh 12/11/2018 #17

我只是想自己重新理解它。我发现以下方法有帮助!

• 将 视为与循环内的 if 配对(而不是与 ) 配对 - 如果满足条件,则中断循环,否则这样做 - 除非它是与多个 s 配对的 1!
• 如果完全不满意,则执行 .
• 倍数 s 实际上也可以被认为是 -s!
elseforelseififelseififelif

评论

0赞 Phil 8/22/2020
循环中不需要 if,也不需要循环 - 例如,您可以将 else 与 try-except 一起使用
5赞 Aaron Gable 12/12/2018 #18

这里有一种思考方式,我没有看到其他人在上面提到过:

首先,请记住,for循环基本上只是围绕while循环的语法糖。例如,循环

for item in sequence:
    do_something(item)

可以(大约)改写为

item = None
while sequence.hasnext():
    item = sequence.next()
    do_something(item)

其次,请记住,while 循环基本上只是重复的 if 块!你总是可以把while循环读成“如果这个条件是真的,执行正文,然后回来再次检查”。

因此,while/else 非常有意义:它与 if/else 的结构完全相同,并增加了循环功能,直到条件变为 false,而不仅仅是检查条件一次。

然后 for/else 也非常有意义:因为所有的 for 循环都只是 while 循环之上的语法糖,你只需要弄清楚底层的 while 循环的隐式条件是什么,然后 else 对应于该条件何时变为 False。

-2赞 Jie Zhang 2/14/2019 #19

我认为结构 as (if) A else B,而 for(if)-else 大致是一个特殊的 if-else。理解其他内容可能会有所帮助。

A 和 B 最多执行一次,这与 if-else 结构相同。

for(if) 可以被视为一个特殊的 if,它执行一个循环以尝试满足 if 条件。一旦满足 if 条件,A 和 break;否则,B。

15赞 WloHu 2/22/2019 #20

很好的答案是:

  • 解释了历史,以及
  • 给了权利 引文以方便您的翻译/理解。

我在这里的注释来自 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的句法糖,while-else在其块的末尾具有隐含性。相反的含义是,该循环是 的扩展,更常见(它只是重复/循环的条件检查),因为通常在 之前被教导。然而,事实并非如此,因为这意味着每次当条件为 false 时都会执行 while else 中的块。breakifwhileififwhileelse

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

如果没有 、 等,循环仅在条件不再为真时结束,在这种情况下,块也将执行一次。对于 Python,您必须考虑 C 样式的循环(带条件)或将它们转换为 .breakreturnelseforforwhile

另一个说明:

过早的 , 等 内部循环使条件不可能变为 false,因为当条件为 true 时,执行会跳出循环,并且永远不会再次返回检查它。breakreturn

1赞 Dilux 3/16/2021 #21
for i in range(10):
    print(i)

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

break 关键字用于结束循环。如果 i = 9,则循环将结束。虽然任何如果条件都不太令人满意,那么将完成其余部分。else

10赞 Gabriel Staples 3/24/2021 #22

我想知道 Python 编码人员是如何在脑海中阅读这个结构的(或者大声朗读,如果你愿意的话)。

我只是在脑海中思考:

“不然就没有遇到休息......”

就是这样!

这是因为只有当循环中未遇到语句时,该子句才会执行。elsebreakfor

参考:

请参阅此处:https://book.pythontips.com/en/latest/for_-_else.html#else-clause(强调后加,并将“不”改为“不”):

for循环还有一个我们大多数人都不熟悉的子句。else 子句在循环正常完成后执行。这意味着循环没有遇到中断语句。else


话虽如此,我建议不要使用这种不寻常的语言特征。不要在 for 循环后使用子句。这让大多数人感到困惑,并且只会减慢他们阅读和理解代码的能力。else

评论

1赞 Nik O'Lai 5/5/2023
我无法说服自己,正常完成循环是通过语句完成的。对我来说,情况并非如此。因此,没有使用这种奇怪的过度思考结构。break
1赞 Mhmoud Sabry 9/6/2021 #23

else 子句在循环正常完成后执行。这意味着 :==> else 块紧随 for/while 之后,仅在循环未被 break 语句终止时执行

for item in lista:
if(obj == item ):
    print("if True then break will run and else not run")
    break;
else:
print("in  else => obj not fount ")
2赞 Harley 11/11/2022 #24

循环的 else 分支执行一次,无论循环是否进入其主体,除非循环主体已进入但未完成。也就是说,在循环中会遇到中断或返回语句。

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

其他时间也一样。

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
2赞 Alireza Fattahi 7/26/2023 #25

对于程序员来说,这似乎令人困惑,因为我们总是希望在面对 时看到,但在现实生活中,我们使用ifelseelsefor

举个例子,我让我的儿子在书架上寻找字典,然后把它带给我,如果他找不到,那么他应该去给我买一本

这是在脑海中algorithmhis

for book in bookshelf:
    if book == 'dictionary':
        #Lucky Me !! I find it lets bring it to dad
        bring('dictionary')
        break #and of course I break and stop searching 
else: #too bad :( we do not have any dictionaries
    buy('dictionary');