Python使用异常控制流被认为是坏的?

Spe*_*bun 19 python generator try-catch

行,

我过去曾多次看过这个,但最近我的问题在这里.所以,我很好奇为什么会这样,在python中,因为生成器使用异常来指示数据的结束.

如果对于每个使用python的人都这么糟糕,为什么语言将它包含在被认为是基本控制结构的内容中呢?对于那些想要阅读相关PEP的人,请访问此处.

Jon*_*erg 13

因为结束生成器不是一个常见的事件(我知道它总会发生,但它只发生一次).抛出异常被认为是昂贵的.如果一个事件在99%的时间内成功并且失败1%,那么使用try/except可能比检查是否可以访问该数据要快得多(请求宽恕比允许更容易).

还有一个偏见,因为尝试/除了这样使用的块可能很难理解.流控制可能难以遵循,而if/else更直接.try/except意味着你必须跟踪try中的语句它调用的函数内部的语句的流控制(因为它们可能抛出异常并且它可能向上传播.if/else只能分支在声明被评估.

有时候使用try/except是正确的,以及if/else更有意义的时候.还存在与每个相关的性能成本.考虑:

a = <some dictionary>
if key in a:
    print a[key]
Run Code Online (Sandbox Code Playgroud)

a = <some dictionary>
try:
    print a[key]
except KeyError:
    pass
Run Code Online (Sandbox Code Playgroud)

如果密钥不存在于a中,则第一个会更快,如果它确实存在,则只会稍微(几乎不可察觉).如果密钥确实存在,则第二个将更快,但如果密钥不存在则会慢得多.如果密钥几乎总是存在,那么你选择第二个.否则,第一个更好.

编辑:只是添加一些关于Python try /的东西,除了这有助于解决其中一个可读性问题.

考虑从文件中读取.

f = None
try:
    f = open(filename, 'r')
    ... do stuff to the file ...
except (IOError, OSError):
    # I can never remember which one of these Python throws...
    ... handle exception ...
finally:
    if f:
        f.close()
Run Code Online (Sandbox Code Playgroud)

现在任何东西都do stuff to the file可以抛出异常,我们会抓住它.通常,您尝试在尝试中保留尽可能少的代码,因为这个原因.Python有一个elsetry 的可选子句,只有在try没有遇到异常的情况下运行完成时才会运行.

f = None
try:
    f = open(filename, 'r')
except (IOError, OSError):
    pass
else:
    ... do stuff to the file ...
finally:
    if f:
        f.close()
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您不会有任何可读性问题,因为在try中只有一个语句; 它是一个python标准库函数调用,你只捕获特定的异常.

  • 但是,性能不应该决定什么是惯用的,什么不是(相反,它应该是反向的 - 实现应该,实际上是针对习语优化的).好吧,除了C++之外;) (4认同)