【问题标题】:Inspiration and influence of the else clause of loop statements?循环语句的else子句的启示和影响?
【发布时间】:2011-02-24 20:28:01
【问题描述】:
Python 循环语句可能有一个else 子句,当且仅当循环不 由break 终止时才会执行。换句话说,当条件变为False(while)或迭代器耗尽时(for)。
这个loop-else 结构是否源自另一种语言(理论上的或实际实现的)?有没有更新的语言使用它?
也许我应该问一下 Guido 的前任,但他肯定太忙了,无法进行这种徒劳的询问。 ;-)
相关讨论和例子:
Pythonic ways to use ‘else’ in a for loop
【问题讨论】:
-
-
非常感谢。刚刚检查过它也在教程中提到。 Python 0.9.0 是第一个版本(1991 年 2 月),Python 0.9.1(1991 年 2 月)紧随其后的是“仅微更改”(参见svn.python.org/view*checkout*/python/trunk/Misc/HISTORY) .
-
在 try 之后使用 else 是相关的并且同样有用。 (见simple example。)
-
标签:
python
loops
history
if-statement
【解决方案1】:
在 Common Lisp 的 LOOP 宏 described here by Peter Seibel 中可以找到类似的功能:
...LOOP 提供了两个关键字,initial 和 finally,用于引入要在循环主体之外运行的代码。
在initial 或finally 之后,这些子句由直到下一个循环子句开始或循环结束的所有Lisp 形式组成。所有最初的形式都组合成一个序言,它运行一次,在所有局部循环变量初始化之后和循环体之前。 finally 形式类似地组合成一个结语,以在循环体的最后一次迭代之后运行。序言和尾声代码都可以引用局部循环变量。
序言始终运行,即使循环体迭代零次。如果发生以下任何情况,循环可以在不运行结尾的情况下返回:
- return 子句执行。
- 从正文中的 Lisp 表单中调用 RETURN、RETURN-FROM 或其他控制结构转移...
例如,在链接问题中找到的部分 Python 示例:
for v in known_variables:
if self.bindings[v] is cell:
return v
else:
raise CannotSimplify
可能看起来像这样:
(loop for v in known-variables
when (eq (gethash v (slot-value self bindings)) cell)
do (return v)
finally (signal cannot-simplify))
另一个观察结果:
Common Lisp 的条件系统也是独一无二的。有一次,有人问它来自哪里,并被指向Kent Pitman's paper,他说是从 Maclisp 那里得到的。同样,Common Lisp 看起来怪异的 FORMAT 函数显然来自 Multics 通过Dan Weinreb。
共同点是,语言特征往往不会遵循最能激发该语言灵感的祖先语言,而是被喜爱这些语言的人带到他们正在研究的任何新语言上。因此,如果您想找出 Python 的 for-else 的实际来源,我会查找添加它的人,并查看他们在此之前使用的语言。
【解决方案2】:
我刚刚在this far more general question 的 cmets 中发现了一个相当不错的线索。用户 ΤZΩΤZΙΟΥ 写道:
任何人都记得 FOR var … NEXT var
… END FOR var of Sinclair QL's
超级基础? NEXT之间的一切
和 END FOR 将在最后执行
循环的,除非 EXIT FOR 是
发布。那个语法更干净:)
一个OCR rendition of Sinclair QL User Guide 恰好漂浮在互联网上。上面写着:
NEXT 语句可以放在
环形。它使控制权转到
紧随其后的声明
打开关键字 FOR 或 REPeat。它
应该被视为一种
与 EXIT 语句相反。由一个
奇怪的巧合,这两个词
NEXT 和 EXIT 都包含 EXT。思考
循环的扩展和:
下面是一个有趣的例子:
治安官有一把装有六支枪的枪
子弹,他将向
强盗,但还有两个条件适用:
-
如果他击中强盗,他会停下来
射击并返回道奇城。
-
如果他在击中子弹之前用完了子弹
强盗,他告诉他的伙伴注意
他(警长)回来时的强盗
到道奇城。
100 REMark Western FOR with Epilogue
110 FOR bullets = 1 TO 6
120 PRINT "Take aim"
130 PRINT "FIRE A SHOT"
140 LET hit= RND(0 TO 1)
150 IF hit = 1 THEN EXIT bullets
160 NEXT bullets
170 PRINT "Watch Bandit"
180 END FOR bullets
190 PRINT "Return to Dodge City"
因此,在不同的(并且可以说是不那么令人不安的)语法下,它的语义完全相同。
维基百科告诉我们,Sinclair QL 于 1984 年 2 月作为 Sinclair ZX Spectrum 的继任者推出,但未能取得商业成功。