尝试/抓住或validation速度?

我正在使用Python,每当我必须validation函数input时,我认为input工作,然后发现错误。

在我的情况下,我有一个通用的Vector()类,我用了几个不同的东西,其中之一是增加。 它既作为Color()类也作为Vector() ,所以当我向Color()添加标量时,应该将该常量添加到每个单独的组件中。 Vector()Vector()添加需要按组件方式添加。

这个代码被用于光线跟踪器,所以任何速度提升都很好。

这是我的Vector()类的简化版本:

 class Vector: def __init__(self, x, y, z): self.x = x self.y = y self.z = z def __add__(self, other): try: return Vector(self.x + other.x, self.y + other.y, self.z + other.z) except AttributeError: return Vector(self.x + other, self.y + other, self.z + other) 

我目前正在使用try...except方法。 有人知道更快的方法吗?


编辑:感谢您的答案,我尝试和testing下面的解决scheme,在添加Vector()对象之前专门检查类名称:

 class Vector: def __init__(self, x, y, z): self.x = x self.y = y self.z = z def __add__(self, other): if type(self) == type(other): return Vector(self.x + other.x, self.y + other.y, self.z + other.z) else: return Vector(self.x + other, self.y + other, self.z + other) 

我使用timeit对这两个代码块进行了速度testing,结果非常显着:

  1.0528049469 usec/pass for Try...Except 0.732456922531 usec/pass for If...Else Ratio (first / second): 1.43736090753 

我还没有testingVector()类, 没有任何inputvalidation(即移动检查出的类和实际的代码),但我想像它甚至比if...else方法更快。


最新更新 :回顾这段代码,这不是一个最佳解决scheme。

OOP使得这个更快:

 class Vector: def __init__(self, x, y, z): self.x = x self.y = y self.z = z def __add__(self, other): return Vector(self.x + other.x, self.y + other.y, self.z + other.z) class Color(Vector): def __add__(self, other): if type(self) == type(other): return Color(self.x + other.x, self.y + other.y, self.z + other.z) else: return Color(self.x + other, self.y + other, self.z + other) 

我提出了马特·乔伊纳(Matt Joiner)的回答,但是希望包括一些额外的观察结果,以表明除了一些其他因素之外,在预先检查的条件之间进行select时有4倍的问题(称为LBYL或“ “),只是处理例外(称为EAFP或”容易要求宽恕而不是权限“)。

这些时间是:

  • LBYL检查成功时的时机
  • LBYL检查失败时的定时
  • EAFP 抛出exception时的定时
  • EAFP抛出exception时的定时

其他因素是:

  • 检查成功/失败或exception抛出/不抛出的典型比例
  • 是否存在妨碍使用LBYL的竞赛条件

最后一点是需要首先解决的问题:如果有潜在的竞争条件,那么你别无select, 必须使用exception处理。 一个典型的例子是:

 if <dir does not exist>: <create dir> # May still fail if another process creates the target dir 

由于LBYL并不排除这种情况,所以它没有提供真正的好处,也没有任何判断力:EAFP是正确处理竞争条件的唯一方法。

但是如果没有竞争条件,任何一种方法都是可行的。 他们提供不同的权衡:

  • 如果没有例外,EAFP就接近免费
  • 但是,如果发生exception,则相对昂贵,因为在展开堆栈,创buildexception并将其与exception处理子句进行比较时涉及很多处理
  • 相比之下,LBYL会带来潜在的高固定成本:无论成功或失败,都会执行附加检查

那么会导致以下决定标准:

  • 这段代码是否被认为对应用程序的速度至关重要? 如果不是,那么不要担心两者哪一个更快,担心哪一个更容易阅读。
  • 预检是否比筹集和捕捉exception的成本贵? 如果是,那么EAFP总是更快,应该使用。
  • 如果答案是“否”,事情会变得更有趣。 在这种情况下,更快取决于成功还是错误情况更为普遍,以及预检和exception处理的相对速度。 明确地回答这个问题需要实时测量。

作为一个粗略的经验法则:

  • 如果有潜在的竞争条件,请使用EAFP
  • 如果速度不重要,只要使用您认为更容易阅读的内容即可
  • 如果预检费用昂贵,请使用EAFP
  • 如果您希望操作大部分时间成功*,请使用EAFP
  • 如果您希望操作失败的时间超过一半,请使用LBYL
  • 如果有疑问,测量它

*在这种情况下,人们会在“大部分时间”中看到不同的情况。 对于我来说,如果我希望这个操作能够成功一半以上,那么我当然会使用EAFP,直到我有理由怀疑这段代码是一个实际的性能瓶颈。

在Python中,由于查找次数减less,exception通常会更快。 然而,有一位朋友曾经说过(而且它应该适用于任何语言),假装每次发现exception,都会有一个小的延迟。 避免在延迟可能成为问题时使用例外。

在你给出的例子中,我会去例外。