提问人:Kent Boogaart 提问时间:4/3/2012 最后编辑:Karl KnechtelKent Boogaart 更新时间:7/28/2023 访问量:303396
为什么 python 在 for 和 while 循环之后使用“else”?
Why does python use 'else' after for and while loops?
问:
我了解这个结构是如何工作的:
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
continuewith
我想知道 Python 编码人员是如何在脑海中阅读这个结构的(或者大声朗读,如果你愿意的话)。也许我错过了一些可以使此类代码块更容易破译的东西?
这个问题是关于底层设计决策的,即为什么能够编写这些代码是有用的。另请参阅 Python while 语句上的 Else 子句,了解有关语法含义的具体问题。
答:
因为他们不想在语言中引入新的关键字。每个标识符都会窃取一个标识符并导致向后兼容性问题,因此通常是最后的手段。
评论
finally
finally
completed
这里本来是一个更好的关键词;表示 for 循环的执行没有被破坏(无论是否实际执行了任何循环)。至少这样,如果有人不小心移动了缩进,它最终不会导致不正确的行为,因为 突然移动到了一个构造......else
if
afterBreak
我读了这样的话:
如果仍然有条件运行循环,请做一些事情,否则做其他事情。
评论
for:
else:
else:
你可以把它想象成,就像在其余的东西中一样,或者其他的东西,不是在循环中完成的。else
即使对于经验丰富的 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 线程
评论
for
next((o for o in objects if o.key == search_key), None)
try
except
if
else
for/else
else
for
break
else
break
else
for x in [1, 2, 3]:\n print x\n else:\n print 'this executes due to no break'
一个常见的构造是运行一个循环,直到找到某些东西,然后跳出循环。问题是,如果我跳出循环或循环结束,我需要确定发生了哪种情况。一种方法是创建一个标志或存储变量,让我进行第二次测试以查看循环是如何退出的。
例如,假设我需要搜索列表并处理每个项目,直到找到标志项目,然后停止处理。如果缺少标志项,则需要引发异常。
使用 Python ...构建你有for
else
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
评论
Python: the good parts
process
将对 之前存在于列表中的每个元素执行,之后不会对列表中的元素执行,也不会在 上执行。i
theflag
theflag
theflag
else:
passed:
completed:
我认为文档对其他有很好的解释,继续
[...]当循环因列表穷尽而终止时 (with for) 或当条件变为 false (with while) 时,它会执行,但当循环因 break 语句终止时不会执行。
Raymond Hettinger 做了一个精彩的演讲,题为 Transforming Code into Beautiful, Idiomatic Python,他在演讲中简要介绍了该构造的历史。相关部分是“区分循环中的多个出口点”,从 15:50 开始,持续约三分钟。以下是要点:for ... else
- 该结构是由 Donald Knuth 设计的,用于替代某些用例;
for ... else
GOTO
- 重用这个关键词是有道理的,因为“这是 Knuth 使用的,人们知道,当时,所有的 [语句] 都嵌入了 和 下面,他们希望
else
for
if
GOTO
else
;" - 事后看来,它应该被称为“no break”(或者可能是“nobreak”),这样就不会混淆了。
因此,如果问题是“他们为什么不更改这个关键字?”那么 Cat Plus Plus 可能给出了最准确的答案——在这一点上,它对现有代码的破坏性太大而无法实用。但是,如果你真正要问的问题是为什么一开始就被重用了,那么,显然这在当时似乎是个好主意。else
就我个人而言,我喜欢在可能被误认为属于循环内部的地方进行内联评论的折衷方案。它相当清晰和简洁。这个选项在 Bjorn 在回答末尾链接的摘要中得到了简要提及:# no break
else
为了完整起见,我应该提到这一点,但略有变化 语法,想要这种语法的程序员现在可以拥有它:
for item in sequence: process(item) else: # no break suite
* 视频那部分的额外引述:“就像我们调用 lambda makefunction 一样,没有人会问,'lambda 是做什么的?'”
评论
for ... else
break
我把它读成“当 完全耗尽,并且执行即将在完成 之后进入下一个语句时,else 子句将被执行。因此,当迭代被 中断时,这将不会被执行。iterable
for
break
我发现“获取”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
评论
for:
else:
else
then:
else
我同意,这更像是一个“elif not [条件提高休息]”。
我知道这是一个老话题,但我现在正在研究同一个问题,我不确定是否有人以我所理解的方式抓住了这个问题的答案。
对我来说,有三种方式可以“阅读”in或语句,它们都是等价的,是:else
For... else
While... else
else
==
if the loop completes normally (without a break or error)
else
==
if the loop does not encounter a break
else
==
else not (condition raising break)
(大概有这样的条件,否则你不会有循环)
因此,从本质上讲,循环中的“else”实际上是一个“elif ...”其中“...”是 (1) 无中断,相当于 (2) 不是 [条件提高中断]。
我认为关键是没有“中断”是没有意义的,所以包括:else
for...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
----------
由于技术部分已经得到了很好的回答,我的评论只是与产生这个回收关键字的混淆有关。
由于 Python 是一种非常有说服力的编程语言,因此误用关键字更为臭名昭著。这个关键词完美地描述了决策树流程的一部分,“如果你不能做这个,(否则)做那个”。这是用我们自己的语言暗示的。else
相反,将此关键字与 and 语句一起使用会导致混淆。原因是,我们作为程序员的职业生涯告诉我们,语句存在于决策树中;它的逻辑作用域,一个有条件地返回要遵循的路径的包装器。同时,循环语句有一个比喻性的明确目标,即达到某种目的。在过程的不断迭代后,目标才得以实现。while
for
else
if / else
指示要遵循的路径。循环遵循路径,直到“目标”完成。
问题在于,这是一个明确定义条件中最后一个选项的词。该词的语义由 Python 和 Human Language 共享。但是人类语言中的“else”这个词从来不用于表示某人或某事在某事完成后将采取的行动。如果在完成过程中出现问题(更像是中断语句),将使用它。else
最后,关键字将保留在 Python 中。很明显,这是错误的,当每个程序员都试图想出一个故事来理解它的用法时,就像一些助记符一样。如果他们选择了关键字,我会很高兴.我相信这个关键词完全适合这个迭代流程,即循环后的回报。then
它类似于某个孩子在组装玩具的每一步后遇到的情况:然后呢,爸爸?
评论
语句块中的代码将在循环未中断时执行。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 语句,以及循环上的 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
评论
关键字在这里可能会令人困惑,正如许多人所指出的那样,像这样的东西更合适。else
nobreak
notbreak
为了从逻辑上理解,将其与 ,而不是 进行比较,大多数 python 程序员都熟悉以下代码:for ... else ...
try...except...else
if...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.
同样,可以将其视为一种特殊的:break
Exception
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
区别是隐含的,你不能把它写出来,所以它变成了:python
except break
for x in iterable:
do_something(x)
else:
print('no break encountered') # No break statement was encountered
是的,我知道这种比较可能很困难和令人厌烦,但它确实澄清了混乱。
评论
try: stuff(); except: error(); else: ok()
try: stuff(); ok(); except: error()
else
为了简单起见,你可以这样想;
- 如果在循环中遇到该命令,则不会调用该部件。
break
for
else
- 如果在循环中没有遇到该命令,则将调用该部件。
break
for
else
换言之,如果 for 循环迭代没有 “中断” ,则该部分将被调用。break
else
评论
else
for/else
for/nobreak
这是除了搜索之外的另一个惯用用例。假设您想等待条件为真,例如在远程服务器上打开端口,以及一些超时。然后,您可以使用如下结构: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()
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
评论
我只是想自己重新理解它。我发现以下方法有帮助!
• 将 视为与循环内的 if
配对(而不是与 ) 配对 - 如果满足条件,则中断循环,否则这样做 - 除非它是与多个 s 配对的 1!
• 如果完全不满意,则执行 .
• 倍数 s 实际上也可以被认为是 -s!else
for
else
if
if
else
if
if
elif
评论
这里有一种思考方式,我没有看到其他人在上面提到过:
首先,请记住,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。
我认为结构 as (if) A else B,而 for(if)-else 大致是一个特殊的 if-else。理解其他内容可能会有所帮助。
A 和 B 最多执行一次,这与 if-else 结构相同。
for(if) 可以被视为一个特殊的 if,它执行一个循环以尝试满足 if 条件。一旦满足 if 条件,A 和 break;否则,B。
很好的答案是:
我在这里的注释来自 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 中的块。break
if
while
if
if
while
else
为了便于理解,可以这样想:
如果没有 、 等,循环仅在条件不再为真时结束,在这种情况下,块也将执行一次。对于 Python,您必须考虑 C 样式的循环(带条件)或将它们转换为 .
break
return
else
for
for
while
另一个说明:
过早的 , 等 内部循环使条件不可能变为 false,因为当条件为 true 时,执行会跳出循环,并且永远不会再次返回检查它。
break
return
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
我想知道 Python 编码人员是如何在脑海中阅读这个结构的(或者大声朗读,如果你愿意的话)。
我只是在脑海中思考:
“不然就没有
遇到休息
......”
就是这样!
这是因为只有当循环中未遇到语句时,该子句才会执行。else
break
for
参考:
请参阅此处:https://book.pythontips.com/en/latest/for_-_else.html#else-clause(强调后加,并将“不”改为“不”):
for
循环还有一个我们大多数人都不熟悉的子句。else
子句在循环正常完成后执行。这意味着循环没有遇到中断语句。else
话虽如此,我建议不要使用这种不寻常的语言特征。不要在 for 循环后使用子句。这让大多数人感到困惑,并且只会减慢他们阅读和理解代码的能力。else
评论
break
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 ")
循环的 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
对于程序员来说,这似乎令人困惑,因为我们总是希望在面对 时看到,但在现实生活中,我们使用if
else
else
for
举个例子,我让我的儿子在书架上寻找字典,然后把它带给我,如果他找不到,那么他应该去给我买一本
这是在脑海中algorithm
his
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');
评论
break
else
for ... else foo()
foo()
break