我理解这种结构是如何运作的:
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子句,了解语法含义的具体问题。
这里的else关键字可能会让人困惑,正如许多人指出的那样,像nobreak, notbreak这样的关键字更合适。
为了理解……其他的……从逻辑上讲,将它与try进行比较……Else,不是if…Else…,大多数python程序员都熟悉以下代码:
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视为一种特殊的异常:
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暗示除了break,你不能把它写出来,所以它变成:
for x in iterable:
do_something(x)
else:
print('no break encountered') # No break statement was encountered
是的,我知道这种比较可能会很困难和令人厌倦,但它确实澄清了困惑。
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是做什么的?’”
下面是一种我从未见过其他人提到过的思考方法:
首先,请记住for循环基本上只是while循环的语法糖。例如,循环
for item in sequence:
do_something(item)
可以重写(大约)为
item = None
while sequence.hasnext():
item = sequence.next()
do_something(item)
其次,记住while循环基本上只是重复if块!你总是可以把while循环读成“如果这个条件为真,执行body,然后回来再次检查”。
因此while/else非常有意义:它与if/else结构完全相同,只是增加了循环直到条件变为false的功能,而不是只检查一次条件。
然后for/else也非常有意义:因为所有的for循环都只是while-循环之上的语法糖,你只需要弄清楚底层while-循环的隐式条件是什么,然后else对应于当条件变为False时。
一个常见的构造是运行一个循环,直到找到一些东西,然后跳出循环。问题是,如果我跳出循环或循环结束,我需要确定发生了哪种情况。一种方法是创建一个标志或存储变量,让我进行第二次测试,以查看循环是如何退出的。
例如,假设我需要在列表中搜索并处理每个项,直到找到标志项,然后停止处理。如果缺少标志项,则需要引发异常。
使用Python进行…你的其他构念
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.")
在第一种情况下,raise与它所使用的for循环紧密绑定。第二种情况是,绑定不那么牢固,在维护过程中可能会出现错误。