尝试/抓住或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,都会有一个小的延迟。 避免在延迟可能成为问题时使用例外。
在你给出的例子中,我会去例外。