python循环/关键字的黑暗角落。风格建议

时间:2015-04-11 01:47:53

标签: python loops keyword

学习python,找到了这段代码。它从标准输入读取文本并打印"完成"什么时候结束我从未在任何其他语言的任何地方看到过else循环while。在我发现这个网站的评论中说这是一种类似于finally的pythonic方式,但是用于while循环。

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

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

2 个答案:

答案 0 :(得分:6)

使用while / else的基本想法当然是Pythonic - 否则就不会出现这种语言。

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


首先,你无法退出循环(除了异常)。 readline在EOF返回一个空字符串,这可能是您要检查的内容:

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

但接下来,我不确定while / else是否符合您的想法。我认为你期望它运行else然而你退出循环。但正如the docs解释:

  

在第一个套件中执行的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")

作为旁注,使用readlinewhile循环break几乎不需要;像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"),但违反这些简单的内容会分散读者的注意力,注意可能存在更高级别的违规行为那你在问。

答案 1 :(得分:0)

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