当前位置: 首页 > 面试题库 >

尝试/捕捉或验证速度?

鲁华灿
2023-03-14
问题内容

我正在使用Python,每当必须验证函数输入时,我都认为输入有效,然后捕获了错误。

就我而言,我有一个通用Vector()类,用于一些不同的事情,其中​​之一是加法。它既作为Color()类又作为a起作用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方法。有人知道更快的方法吗?

编辑: 由于有了答案,我尝试并测试了以下解决方案,该解决方案在添加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结果非常显着:

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

我没有在 没有 输入验证的情况下测试过Vector()该类(即将检查移出该类并移至实际代码中),但是我想它比该方法还要快。
__if...else

较晚更新 :回顾此代码,这 不是 最佳解决方案。

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)的回答,但想补充一些观察意见,以使我们清楚地了解,与其他几个因素相比,在预检查条件之间进行选择时,有 4
倍的重要性(被称为LBYL或“请先检查一下”) ”),并且仅处理异常(称为EAFP或“比许可更容易请求宽恕”)。

这些时间是:

  • LBYL检查 成功 的时间
  • LBYL检查 失败 的时间
  • 当异常定时 与EAFP抛出
  • 当异常时序 与EAFP抛出

其他因素是:

  • 检查成功/失败或引发异常/未引发案例的典型比率
  • 是否存在禁止使用LBYL的比赛条件

最后一点是首先需要解决的问题:如果存在争用条件的可能性,那么您别无选择, 必须 使用异常处理。一个典型的例子是:

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

由于LBYL并不排除此类情况的例外,因此它没有真正的好处,也没有做出判断的要求:EAFP是唯一可以正确处理比赛条件的方法

但是,如果没有竞争条件,则两种方法都可能可行。它们提供了不同的权衡:

  • 如果没有异常,那么EAFP几乎是免费的
  • 但是,如果发生异常,则相对昂贵,因为展开堆栈,创建异常并将其与异常处理子句进行比较涉及大量处理
  • 相比之下,LBYL可能会产生较高的固定成本:无论成功与否,始终执行附加检查

然后得出以下决策标准:

  • 是否知道这段代码对应用程序的速度至关重要?如果不是,那么不必担心两者中的哪一个更快,而不必担心两者中的哪一个更容易阅读。
  • 预检是否比引发和捕获异常的成本贵?如果是,则EAFP总是更快,应该使用。
  • 如果答案为“否”,事情就会变得更加有趣。在那种情况下,更快的速度取决于成功或错误情况是否更常见,以及预检查和异常处理的相对速度。明确地回答这个问题需要实际的时序测量。

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

  • 如果存在潜在的比赛条件,请使用EAFP
  • 如果速度不是很关键,请使用您认为更易于理解的方式
  • 如果预检查价格昂贵,请使用EAFP
  • 如果您希望操作在大多数时间都能成功*,请使用EAFP
  • 如果您期望操作失败超过一半的时间,请使用LBYL
  • 如有疑问,请进行测量

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



 类似资料:
  • 我的项目由一个小图标组成,它在一个尺寸为25×20的网格上移动。我知道我可以用几个if/else块轻松地完成这项工作,但我想了解更多关于错误处理的知识。 我当时想的是使用try-catch,但它根本不会捕获数组索引越界异常或任何:它不会返回“error”或位置,因此它永远不会进入catch块。 我在想这样的伪代码: 实际代码:

  • 我在使用这个try/catk语句时遇到了麻烦。我试图用它抛出一条错误消息,上面写着,“请输入一个整数!”如果用户输入一个字母。我使用的第一个成功了,但是它最终需要两行用户输入,而不仅仅是一行,所以它基本上跳过了一个应该问的问题。在那之后,其他的都不起作用,它们只是被完全跳过。我还需要对用户输入做同样的事情,如果用户在字母应该在的地方输入整数,它会抛出一条错误消息,上面写着“请输入字符串!”。我知道

  • 问题内容: 我需要捕捉一些从PHP本机函数抛出的警告,然后处理它们。 特别: DNS查询失败时,它将引发警告。 / 不起作用,因为警告也不例外。 我现在有2个选择: 似乎有点过分,因为我必须使用它来过滤页面中的每个警告(这是真的吗?); 调整错误报告/显示,以使这些警告不会在屏幕上显示,然后检查返回值;如果为,则找不到主机名的记录。 这里的最佳做法是什么? 问题答案: 设置和还原错误处理程序 一种

  • 我在do while loop中尝试执行try-catch语句时遇到了一个问题,我要求用户首先输入字母,然后输入一个数字,如果他输入正确,程序结束;如果他输入字母而不是数字,程序应该说“发生错误,请输入数字”,并要求用户再次输入数字,但每次我输入字母而不是数字,程序就进入了一个无限循环,不允许我输入新的值。只是说“发生错误,您必须输入数字”“请输入数字”。

  • 我的sp中有一个try catch块,try中只有一个insert语句。捕捉检查错误代码,如果是pk违规,如果是则做更新。但是有时我会得到“当前事务不能被提交,不能支持写入日志文件的操作。回滚事务。 在批处理结束时检测到不可提交的事务。事务被回滚了“,所以我添加了xact_abort,但后来我不断得到”EXECUTE之后的事务计数表明 BEGIN 和 COMMIT 语句的数量不匹配“,我发现了这一

  • 我想嵌套一个try catch,但内部try中没有捕获。 例如: 这可能吗?这是一种良好的做法吗?