ale*_*xis 187 python loops for-loop while-loop
许多Python程序员可能没有意识到while循环和for循环的语法包含一个可选else:子句:
for val in iterable:
do_something(val)
else:
clean_up()
Run Code Online (Sandbox Code Playgroud)
该else子句的主体是某些清理操作的好地方,并且在循环的正常终止时执行:即,退出循环return或break跳过该else子句; continue执行后退出.我知道这只是因为我只是看着它(再次),因为我永远记得当该else子句被执行.
总是?关于循环的"失败",顾名思义?定期终止?即使循环退出return?如果不抬头,我永远无法完全确定.
我责怪我对关键词选择的持续存在的不确定性:我发现else这种语义非常缺乏统一性.我的问题不是"为什么这个关键字用于此目的"(我可能会投票关闭,但只有在阅读了答案和评论后),但我怎么能想到else关键字,以便它的语义有意义,我因此能记得吗?
我确信对此有相当多的讨论,我可以想象选择是为了与try语句的else:条款(我也必须查找)保持一致,并且目标是不添加到列表中Python的保留字.也许选择的理由else将澄清其功能并使其更令人难忘,但我将名称与功能联系起来,而不是在历史解释本身之后.
这个问题的答案,我的问题简要地作为副本被关闭,包含了很多有趣的背景故事.我的问题有一个不同的焦点(如何连接else关键字选择的特定语义),但我觉得应该有一个链接到这个问题的某个地方.
dra*_*woc 210
(这是受@Mark Tolonen的回答启发的.)
如果if语句else的条件求值为false,则语句将运行其子句.同样,如果while循环的条件求值为false ,则循环运行else子句.
此规则与您描述的行为相匹配:
break语句时,退出循环而不评估条件,因此条件不能计算为false,并且您永远不会运行else子句.continue语句时,再次评估条件,并完成您在循环迭代开始时的正常操作.因此,如果条件为true,则保持循环,但如果为false,则运行else子句.return,不评估条件,因此不运行else子句.for循环的行为方式相同.如果迭代器具有更多元素,则将条件视为true,否则将其视为false.
Mos*_*oye 36
最好以这种方式来考虑它:如果前一个块中的所有内容都正确,那么else将始终执行该块,以使其达到耗尽状态.for
用鼠标右键在这种情况下将意味着没有exception,没有break,没有return.任何劫持控制权的声明for都会导致该else块被绕过.
搜索某个项目时会发现一个常见的用例iterable,当找到该项目或"not found"通过以下else块提出/打印标记时,将搜索该项目:
for items in basket:
if isinstance(item, Egg):
break
else:
print("No eggs in basket")
Run Code Online (Sandbox Code Playgroud)
A continue不会劫持控制for,因此控制将else在for耗尽后继续进行.
Mar*_*nen 31
什么时候if执行else?当它的条件是假的.它与while/ 完全相同else.所以你可以认为while/ else只是一个if在它评估为false之前一直运行它的真实条件.A break不会改变这一点.它只是包含循环的跳转而没有评估.该else如果仅执行评估的if/ while条件为假.
这for是类似的,除了它的错误条件是耗尽它的迭代器.
continue并且break不执行else.那不是他们的功能.在break退出循环含有.将continue返回到循环包含,其中,所述循环条件被评估的顶部.它是评估if/ while错误(或for没有更多项目)执行的行为,else而不是其他方式.
Ale*_*all 24
这就是它的本质意义:
for/while ...:
if ...:
break
if there was a break:
pass
else:
...
Run Code Online (Sandbox Code Playgroud)
这是编写这种常见模式的更好方法:
found = False
for/while ...:
if ...:
found = True
break
if not found:
...
Run Code Online (Sandbox Code Playgroud)
else如果有一个return因为return离开函数,则不会执行该子句.您可能想到的唯一例外是finally,其目的是确保它始终执行.
continue与此事无关.它导致循环的当前迭代结束,这可能发生在整个循环结束,并且显然在这种情况下循环不是由a结束break.
try/else 类似:
try:
...
except:
...
if there was an exception:
pass
else:
...
Run Code Online (Sandbox Code Playgroud)
Kei*_*wan 20
如果你认为你的循环是一个类似于此的结构(有点伪代码):
loop:
if condition then
... //execute body
goto loop
else
...
Run Code Online (Sandbox Code Playgroud)
它可能会更有意义.循环本质上只是一个if重复的语句,直到条件为止false.这是重点.循环检查它的状态并看到它false,因此执行else(就像正常一样if/else)然后完成循环.
因此,请注意在else 检查条件时执行的唯一get.这意味着如果您在执行过程中使用例如a return或a 退出循环体break,因为不再检查条件,else则不会执行该情况.
continue另一方面,A 停止当前执行,然后再跳回以再次检查循环的状态,这就是else在这种情况下可以达到的原因.
nas*_*-sh 14
我对循环else条款的关注时刻是我正在观看Raymond Hettinger的演讲时,他讲述了一个关于他应该如何调用它的故事nobreak.看看下面的代码,您认为它会做什么?
for i in range(10):
if test(i):
break
# ... work with i
nobreak:
print('Loop completed')
Run Code Online (Sandbox Code Playgroud)
你会猜到它会怎么样?好吧,nobreak只有break在循环中没有命中语句时才会执行所说的部分.
通常我倾向于想到这样的循环结构:
for item in my_sequence:
if logic(item):
do_something(item)
break
Run Code Online (Sandbox Code Playgroud)
要像可变数量的if/elif语句一样:
if logic(my_seq[0]):
do_something(my_seq[0])
elif logic(my_seq[1]):
do_something(my_seq[1])
elif logic(my_seq[2]):
do_something(my_seq[2])
....
elif logic(my_seq[-1]):
do_something(my_seq[-1])
Run Code Online (Sandbox Code Playgroud)
在这种情况下,elsefor循环上的else语句与elifs 链上的语句完全相同,只有在它之前没有任何条件计算为True时才会执行.(或打破执行return或异常)如果我的循环不符合此规范,我通常会选择退出使用for: else,因为您发布此问题的确切原因:它不直观.
其他人已经解释过它的机制while/for...else,而且Python 3语言参考有权威的定义(参见while和for),但这是我的个人助记符FWIW.我想我的关键是将其分解为两部分:一部分用于理解else与循环条件相关的含义,一部分用于理解循环控制.
我发现最简单的理解是while...else:
while你有更多的东西,做的东西,else如果你用完了,这样做
该for...else助记符是基本相同的:
for每个项目,做的东西,但else如果你用完了,这样做
在这两种情况下,else只有在没有更多要处理的项目时才会到达该部分,并且最后一项已经以常规方式处理(即无break或return).一个continue刚刚回到如果有任何更多的项目看.我对这些规则的助记符适用于:while和for:
当进入
break或进入时,return没有什么else可做的,
当我说continue,那就是为你"循环回来"
- 用"循环回启动"意味着,显然,循环的开始,我们检查迭代中是否还有更多的项目,所以就此else而言,continue根本不起作用.
在测试驱动开发(TDD)中,当使用Transformation Priority Premise范例时,您将循环视为条件语句的泛化.
如果您只考虑简单if/else(无elif)语句,这种方法与此语法结合得很好:
if cond:
# 1
else:
# 2
Run Code Online (Sandbox Code Playgroud)
概括为:
while cond: # <-- generalization
# 1
else:
# 2
Run Code Online (Sandbox Code Playgroud)
很好.
在其他语言中,从单个案例到具有集合的案例的TDD步骤需要更多重构.
以下是8thlight博客的示例:
在8thlight博客的链接文章中,我们考虑使用Word Wrap kata:在字符串中添加换行符(s下面的代码段中的变量),使它们适合给定的宽度(length下面片段中的变量).有一次,实现如下(Java):
String result = "";
if (s.length() > length) {
result = s.substring(0, length) + "\n" + s.substring(length);
} else {
result = s;
}
return result;
Run Code Online (Sandbox Code Playgroud)
而目前失败的下一个测试是:
@Test
public void WordLongerThanTwiceLengthShouldBreakTwice() throws Exception {
assertThat(wrap("verylongword", 4), is("very\nlong\nword"));
}
Run Code Online (Sandbox Code Playgroud)
因此,我们的代码可以有条件地运行:当满足特定条件时,会添加换行符.我们希望改进代码以处理多个换行符.文章中提出的解决方案建议应用(if-> while)转换,但作者发表评论:
虽然循环不能有
else子句,所以我们需要通过在else路径中少做一些来消除if路径.同样,这是一个重构.
它强制在一个失败测试的上下文中对代码进行更多更改:
String result = "";
while (s.length() > length) {
result += s.substring(0, length) + "\n";
s = s.substring(length);
}
result += s;
Run Code Online (Sandbox Code Playgroud)
在TDD中,我们希望尽可能少地编写代码以使测试通过.感谢Python的语法,可以进行以下转换:
从:
result = ""
if len(s) > length:
result = s[0:length] + "\n"
s = s[length:]
else:
result += s
Run Code Online (Sandbox Code Playgroud)
至:
result = ""
while len(s) > length:
result += s[0:length] + "\n"
s = s[length:]
else:
result += s
Run Code Online (Sandbox Code Playgroud)
我看到它的方式,else:当你迭代循环结束时触发.
如果您break或return或raise你不重复过去的循环的结尾,你停下immeadiately,因而else:块将不会运行.如果你continue仍然迭代循环结束,那么继续只是跳到下一次迭代.它不会停止循环.
带有while子句else的语句
while condition:\n iteration\nelse:\n conclusion\nRun Code Online (Sandbox Code Playgroud)\n完全等于
\nwhile True:\n if not condition:\n conclusion\n break\n iteration\nRun Code Online (Sandbox Code Playgroud)\n带有for子句else的语句
for item in iterable:\n iteration\nelse:\n conclusion\nRun Code Online (Sandbox Code Playgroud)\n完全等于
\niterator = iter(iterable)\nwhile True:\n try:\n item = next(iterator)\n except StopIteration:\n conclusion\n break\n iteration\nRun Code Online (Sandbox Code Playgroud)\n它有助于理解迭代语句中breakor语句的效果。continue
笔记。\xe2\x80\x94 对于不带子句的whileand语句,将结论语句替换为等效代码中的语句。forelsepass
| 归档时间: |
|
| 查看次数: |
11844 次 |
| 最近记录: |