蟒蛇循环/关键字的黑暗角落.风格建议



学习python,找到了这个代码片段。它从 stdin 读取文本,并在完成后打印"完成"。我从未见过任何其他语言在其他任何地方while循环的else。我发现这个的网站上的评论说这是一种类似于finally但有一段时间循环的pythonic方法。

import sys
while True:
line = sys.stdin.readline()
if not line:
break
else:
print("Done");

问题是,这是蟒蛇吗?我工作的地方有非常严格的 pep-8 合规政策,所以我需要知道这是否可以。

使用while/else的基本思想当然是 Pythonic——否则它就不会出现在语言中。

但是,代码中有两个 bug,每个 bug 都意味着else代码永远不会运行。包含永远不会执行的代码可能不是 Pythonic,它只是为了误导读者。:)更重要的是,这可能不是你想要的。


首先,你永远无法退出循环(除非有例外)。readline在 EOF 返回一个空字符串,因此这可能是您要检查的内容:

while True:
line = sys.stdin.readline()
if line:
print(line)
else:
break
else:
print("Done")

但接下来,我不确定while/else做了你认为它做的事情。我认为您希望它运行else无论您退出循环。但正如文档所解释的那样:

在第一个套件中执行的break语句终止循环而不执行else子句的套件。

换句话说,else部分仅在您正常退出时运行,条件变为 false。显然,while True永远不会变成虚假。

这就是重点:有时你需要区分正常循环整理与以if something: break退出;这就是你使用else:的时候。如果你想以任何一种方式做同样的事情,只需这样做:

while True:
line = sys.stdin.readline()
if line:
print(line)
else:
break
print("Done")

如果你想要一些"类似于finally"的东西,因为你可能有例外,答案很简单:使用finally

try:
while True:
line = sys.stdin.readline()
if line:
print(line)
else:
break
finally:
print("Done")

作为旁注,几乎不需要用whilebreak遍历readline;像sys.stdin这样的类似文件的对象是行的可迭代对象,与readline返回的行相同,所以你可以这样做:

for line in sys.stdin:
print(line)
print("Done")

作为旁注,在代码中使用不必要的括号和分号通常被认为是 Pythonic 的——尤其是当它使你的代码看起来像 C 或 Java 或其他东西时。虽然PEP 8只是作为Python stdlib的标准,但许多人将其用作自己的Python软件的指南,除非您有充分的理由不遵循其建议,否则最好遵循它的建议。您可以使用pep8等工具来检查您是否遵循了指南。这只会捕获简单的东西,比如你的while(True):而不是while Trueprint("Done");而不是print("Done"),但违反这些简单的东西会分散读者的注意力,无法注意到你问的可能更高级别的违规行为。

事实上,这是实现代码片段目标的pythonic方法。 它被称为 else-for-last-iteration-of-loop (EFLIOL) 习语。

最新更新