我理解这个结构是如何工作的:
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编码器如何在他们的头脑中读取这个结构(或者如果你愿意的话,大声朗读) . 也许我错过了一些会使这些代码块更容易破译的东西?
19 回答
我发现“获取”for / else所做的最简单的方法,更重要的是,什么时候使用它,是专注于break语句跳转到的位置 . For / else构造是一个单独的块 . 休息跳出块,因此跳过'else'条款 . 如果else子句的内容只是跟在for子句之后,它就永远不会被跳过,因此必须通过将它放在if中来提供等效逻辑 . 之前已经说过了,但这些话并不完全,所以它可能对其他人有所帮助 . 尝试运行以下代码片段 . 为了清晰起见,我全心全意地支持“不休息”的评论 .
为了简单起见,你可以这样想;
如果在
for
循环中遇到break
命令,则不会调用else
部分 .如果它在
for
循环中没有遇到break
命令,则会调用else
部分 .换句话说,如果for循环迭代不是"broken"且
break
,则将调用else
部分 .这很简单 .
“别的”这里很简单,只是意思
1,“如果
for clause
完成”它正在挥舞着写出“for clause is completed”这样长的陈述,因此他们引入了“else” .
else
这是一个if的性质 .2,但是,怎么样
for clause is not run at all
所以它的完整陈述是逻辑组合:
或者这样说:
或者这样:
一个常见的构造是运行一个循环直到找到某个东西,然后突破循环 . 问题是,如果我突然出现循环或循环结束,我需要确定发生了哪种情况 . 一种方法是创建一个标志或存储变量,让我进行第二次测试,看看如何退出循环 .
例如,假设我需要搜索列表并处理每个项目,直到找到标记项目然后停止处理 . 如果缺少标志项,则需要引发异常 .
使用Python
for
...else
构造将此与不使用此语法糖的方法进行比较:
在第一种情况下,
raise
与它所使用的for循环紧密绑定 . 在第二种情况下,绑定不那么强,并且在维护期间可能会引入错误 .else
语句块中的代码将在for
循环未被破坏时执行 .来自docs: break and continue Statements, and else Clauses on Loops
我看了它的样子:
如果仍然在运行循环的条件,做的东西,否则做其他事情 .
我把它读作“当
iterable
完全耗尽,并且执行即将进行到完成for
后的下一个语句,将执行else子句 . “因此,当迭代被break
中断时,这将不会被执行 .else
关键字在这里可能令人困惑,正如许多人所指出的那样,nobreak
,notbreak
之类的东西更合适 .为了理解
for ... else ...
逻辑,将它与try...except...else
进行比较,而不是if...else...
,大多数python程序员都熟悉以下代码:同样,将
break
视为一种特殊的Exception
:区别是
python
暗示except break
并且您无法将其写出来,因此它变为:是的,我知道这种比较可能是困难和令人厌烦的,但它确实澄清了混乱 .
Raymond Hettinger的精彩演讲题为Transforming Code into Beautiful, Idiomatic Python,其中简要介绍了
for ... else
构造的历史 . 相关部分为"Distinguishing multiple exit points in loops" starting at 15:50并持续约三分钟 . 以下是要点:由Donald Knuth设计的
for ... else
构造取代了某些GOTO
用例;重用
else
关键字是有意义的,因为“这是Knuth使用的,人们都知道,当时所有[for
语句]都嵌入了if
和GOTO
,他们期望else
;”事后看来,它应该被称为"no break"(或可能是"nobreak"),然后它就不会令人困惑 . *
所以,如果问题是"Why don't they change this keyword?"那么Cat Plus Plus probably gave the most accurate answer - 此时,对现有代码来说实际上太具破坏性了 . 但是如果你真正问的问题是为什么
else
首先被重复使用,那么显然当时这似乎是一个好主意 .就个人而言,我喜欢在线注释
# no break
的妥协,只要else
可能会被误认为是属于循环内部 . 它相当清晰简洁 . 在他的回答结尾处,这个选项在the summary that Bjorn linked中得到了简要的提及:*来自视频部分的奖金引用:“就像我们打电话给lambda makefunction一样,没有人会问,'lambda做什么?'”
您可以将其视为
else
,就像其他内容一样,或其他内容,这些都不是在循环中完成的 .对于经验丰富的Python程序员来说,这是一个奇怪的构造 . 当与for循环一起使用时,它基本上意味着“在迭代中找到一些项目,否则如果没有找到那么......” . 如:
但是只要你看到这个结构,一个更好的选择是将搜索封装在一个函数中:
或者使用列表理解:
它在语义上不等同于其他两个版本,但在非性能关键代码中运行良好,无论您是否迭代整个列表都无关紧要 . 其他人可能不同意,但我个人会避免在 生产环境 代码中使用for-else或while-else块 .
另见[Python-ideas] Summary of for...else threads
我只是想让自己再次理解它 . 我发现以下有帮助!
•将
else
视为与循环内的 if 配对(而不是与for
配对) - 如果条件满足则打破循环,否则执行此操作 - 除了它是else
与多个if
配对!•如果根本没有满足
if
,则执行else
.•多个
if
也可以被认为是if
-elif
s!这里's another idiomatic use case besides searching. Let' s说你想等待条件成立,例如要在远程服务器上打开的端口,以及一些超时 . 然后你可以使用
while...else
结构,如下所示:我认为文档对其他内容有很好的解释,继续
资料来源:Python 2 docs: Tutorial on control flow
I agree, it's more like an 'elif not [condition(s) raising break]'.
我知道这是一个老话题,但我现在正在研究同样的问题,而且我不确定是否有人以我理解的方式捕捉到了这个问题的答案 .
对我来说,在
For... else
或While... else
语句中有"reading"的三种方式,所有这些方法都是等价的,它们是: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)
(可能是有这样的情况,或者你没有循环)So, essentially, the "else" in a loop is really an "elif ..." where '...' is (1) no break, which is equivalent to (2) NOT [condition(s) raising break].
我认为关键是
else
没有'break'是没有意义的,所以for...else
包括:因此,
for...else
循环的基本元素如下所示,您可以用简洁的英语阅读它们:正如其他海报所说,当你有能力时,通常会提高休息时间找到你的循环正在寻找的东西,所以
else:
变成"what to do if target item not located" .Example
您还可以一起使用异常处理,中断和for循环 .
结果
Example
打破中断的简单示例 .
结果
Example
简单示例,没有中断,没有条件提出中断,也没有遇到错误 .
结果
因为他们不想在语言中引入新的关键字 . 每个人窃取一个标识符并导致向后兼容性问题,因此它通常是最后的手段 .
由于技术部分已得到很好的回答,我的评论只与生成此回收关键字的 confusion 有关 .
作为一种非常雄辩的编程语言,滥用关键字更加臭名昭着 .
else
关键字完美地描述了决策树流的一部分"if you can't do this, (else) do that" . 它隐含在我们自己的语言中 .相反,将此关键字与
while
和for
语句一起使用会产生混淆 . 原因是,我们作为程序员的职业生涯告诉我们else
语句存在于决策树中;它的 logical scope ,一个有条件地返回一条路径的包装器 . 同时,循环语句有一个具象的明确目标来达到某种目的 . 在连续迭代过程之后,目标得以实现 .if / else
表示要遵循的路径 . 循环遵循路径,直到"goal"完成 .问题是
else
是一个明确定义条件中最后一个选项的词 . 这个词的 semantics 都由Python和Human Language共享 . 但人类语言中的其他词语从未用于表示某事物完成后某人或某物所采取的行动 . 如果在完成它的过程中问题上升(更像是一个中断声明),它将被使用 .最后,关键字将保留在Python中 . 如果他们选择了关键字
then
,那么's clear it was mistake, clearer when every programmer tries to come up with a story to understand its usage like some mnemonic device. I'已经爱过了 . 我相信这个关键字非常适合迭代流程,循环后的收益 .它类似于一些孩子在完成组装玩具的每一步后所拥有的情况:而且 THEN 爸爸是什么?
这是一种思考方式,我没有看到上面提到过的任何人:
首先,请记住for循环基本上只是while循环的语法糖 . 例如,循环
可以重写(大约)为
其次,请记住while-loops基本上只是重复if-blocks!你总是可以读取一个while循环“如果这个条件成立,执行正文,然后再回来检查” .
因此,while / else非常有意义:它与if / else完全相同,具有循环的附加功能,直到条件变为false而不是仅检查条件一次 .
然后for / else也是完全合理的:因为所有for循环只是while循环之上的语法糖,你只需要弄清楚底层while循环的隐式条件是什么,然后else对应于何时条件变为假 .
让我们假设我们有一个功能
这意味着只有5个没有被打破 . 现在,如果 broken 永远不会被评估为5: -
会给出输出: -
broken 用5评估时的位置: -
它不会打印任何东西 . 因此,间接地告诉至少有一些东西没有被打破 .
但是,如果你想欺骗并跳过你发现的东西,那么你就会被打破 . 也就是说,即使您发现5已损坏,继续循环,否则仍将打印其他语句 . 那是 :-
会打印
我希望它清除混乱,而不是创建一个新的:-)