Python对控制流使用异常被认为是错误的?

Python对控制流使用异常被认为是错误的?,python,try-catch,generator,Python,Try Catch,Generator,好, 我在过去见过很多次,但最近的一次是。所以,我很好奇为什么在python中会出现这种情况,因为生成器使用异常来指示数据的结束 如果这对所有使用python的人来说都很糟糕,那么为什么该语言将其包含在基本的控制结构中呢?对于那些想要阅读相关PEP的人来说。因为异常是在堆栈上提出的,所以它们适用于某些情况,您希望使用其他代码的代码能够捕获异常。例如,考虑要创建一个迭代器的情况,该迭代器使用另一个迭代器的“手动”,有一个例外,您可以从较高的堆栈中捕获并插入自己的逻辑。 ,因为结束生成器不是一个常见

好,

我在过去见过很多次,但最近的一次是。所以,我很好奇为什么在python中会出现这种情况,因为生成器使用异常来指示数据的结束


如果这对所有使用python的人来说都很糟糕,那么为什么该语言将其包含在基本的控制结构中呢?对于那些想要阅读相关PEP的人来说。

因为异常是在堆栈上提出的,所以它们适用于某些情况,您希望使用其他代码的代码能够捕获异常。例如,考虑要创建一个迭代器的情况,该迭代器使用另一个迭代器的“手动”,有一个例外,您可以从较高的堆栈中捕获并插入自己的逻辑。

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

也有人反对它,因为像这样使用try/except块可能很难理解。流量控制可能很难遵循,而if/else则更直接。try/except意味着您必须跟踪try内部及其调用的函数内部语句的流控制(因为它们可能引发异常,并且异常可能向上传播。if/else只能在语句求值时分支)

有时使用try/except是正确的,有时使用if/else更有意义。每种方法都会带来性能成本。请考虑:

a = <some dictionary>
if key in a:
    print a[key]
现在,
do stuff to the file
中的任何内容都可能引发异常,我们将捕获它。通常,由于这个原因,您会尝试在try中保留尽可能少的代码。Python为try提供了一个可选的
else
子句,该子句只有在try运行到完成且未遇到异常时才会运行

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

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

始终使用
try
块进行流控制可能会产生如下代码:

try:
  # stuff
  try:
    if userCondition:
      throw NeedToDoSomethingElseException
    try:
      # stuff
    except NeedToDoSomethingElseException:
      # other stuff
  except NeedToDoSomethingElseException:
    # other stuff
except NeedToDoSomethingElseException:
  # other stuff

撇开性能问题不谈,这不是很优雅。因此,有时使用
try
是完全合适的,但不是所有的都适用。

实用性胜过纯粹性。但性能不应该决定什么是惯用的,什么不是(相反,它应该是相反的-实现应该而且实际上是针对惯用的优化)嗯,除了C++,这是一个很好的答案。我完全同意你的观点,尽管我很好奇为什么你没有包括“代码是为程序员而不是计算机编写的。因此它应该为人编写,而异常作为控制流是不明确的”。我认为性能,尤其是python的性能,是一个比代码库可读性更为次要的日常问题。@Spencer Rathbun主要是因为我有点语无伦次地混淆了两点(一点是关于性能,一点是关于可读性)。@Jonathan Sternberg啊,这就解释了这一点。那么我就接受它作为答案。这不是一个真正的论点,因为同样的情况也会发生在
if
样式中。所以在
if
块中,到处都有等价的
triggerElse
语句?
f = None
try:
    f = open(filename, 'r')
except (IOError, OSError):
    pass
else:
    ... do stuff to the file ...
finally:
    if f:
        f.close()
try:
  # stuff
  try:
    if userCondition:
      throw NeedToDoSomethingElseException
    try:
      # stuff
    except NeedToDoSomethingElseException:
      # other stuff
  except NeedToDoSomethingElseException:
    # other stuff
except NeedToDoSomethingElseException:
  # other stuff