繁体   English   中英

Python中的廉价异常处理?

[英]Cheap exception handling in Python?

我在前面的回答中读到异常处理在Python中很便宜所以我们不应该进行预条件检查。

我以前没有听说过这个,但我对Python比较陌生。 异常处理意味着动态调用和静态返回,而if语句是静态调用,静态返回。

如何做检查是坏的, try-except好,似乎是相反的方式。 谁可以给我解释一下这个?

不要出汗小东西。 您已经选择了一种较慢的脚本语言,因此尝试优化操作码并不会对您有所帮助。 选择像Python这样的解释型动态语言的原因是为了优化你的时间,而不是CPU。

如果您使用通用语言惯用语,那么您将看到快速原型设计和干净设计的所有好处,并且随着新版本的Python发布和计算机硬件升级,您的代码将自然运行得更快。

如果您遇到性能问题,请分析您的代码并优化慢速算法。 但同时,在特殊情况下使用异常,因为它会使你最终在这些方面做的任何重构变得容易得多。

您可能会发现这篇文章很有用: 尝试/除了Python中的性能:一个简单的测试 ,其中Patrick Altman做了一些简单的测试,以查看在条件前检查的各种场景中的性能(在这种情况下特定于字典键)并仅使用例外。 如果您想要调整代码以测试其他条件,也会提供代码。

他得出的结论是:

从这些结果来看,我认为快速确定一些结论是公平的:

  1. 如果该元素很可能不存在,那么最好用has_key检查它。
  2. 如果你提出异常,你不会对异常做任何事情,那么你最好不要让一个人拥有除外
  3. 如果元素可能存在,那么使用try / except块而不是使用has_key有一个非常小的优点,但是,优点非常小。

撇开其他人所说的绩效衡量标准,指导原则通常被定义为“请求宽恕比要求许可更容易”而不是“先跳过去看”。

考虑这两个片段:

# Look before you leap
if not os.path.exists(filename):
    raise SomeError("Cannot open configuration file")
f = open(filename)

# Ask forgiveness ...
try:
  f = open(filename)
except IOError:
  raise SomeError("Cannot open configuration file")

当量? 并不是的。 操作系统是多重系统。 如果在“存在”和“打开”调用的测试之间删除了文件,会发生什么?

如果文件存在但不可读,会发生什么? 如果它是目录名而不是文件怎么办? 可能存在许多可能的故障模式,并且检查所有故障模式是很多工作。 特别是因为“开放”呼叫已经检查并报告所有这些可能的故障。

指南应该是减少状态不一致的可能性,最好的方法是使用异常而不是测试/调用。

“谁可以给我解释一下这个?”

要看。

这是一个解释,但没有用。 你的问题源于你的假设。 由于现实世界与您的假设冲突,它必然意味着您的假设是错误的。 没有太多解释,但这就是你问的原因。

“异常处理意味着动态调用和静态返回,而if语句是静态调用,静态返回。”

“动态电话”是什么意思? 在堆栈帧中搜索处理程序? 我假设你正在谈论的是这个。 并且“静态调用”以某种方式在if语句之后定位块。

也许这种“动态调用”并不是操作中成本最高的部分。 也许if语句表达式评估比简单的“try-it-and-fail”略贵。

事实证明,Python的内部完整性检查几乎与您的if语句相同,并且无论如何都必须完成。 由于Python总是要检查,你的if语句(大多数)是多余的。

您可以在http://docs.python.org/c-api/intro.html#exceptions中阅读有关低级异常处理的内容。


编辑

更重要的是: if和except辩论并不重要。

由于异常很便宜,因此不要将它们标记为性能问题。

使用使您的代码清晰有意义的内容 不要在这样的微优化上浪费时间。

使用Python,很容易检查速度的不同可能性 - 了解timeit模块

...示例会话(使用命令行)比较使用hasattr()与try / except的成本来测试缺少的和当前的对象属性。

% timeit.py 'try:' '  str.__nonzero__' 'except AttributeError:' '  pass'
100000 loops, best of 3: 15.7 usec per loop
% timeit.py 'if hasattr(str, "__nonzero__"): pass'
100000 loops, best of 3: 4.26 usec per loop
% timeit.py 'try:' '  int.__nonzero__' 'except AttributeError:' '  pass'
1000000 loops, best of 3: 1.43 usec per loop
% timeit.py 'if hasattr(int, "__nonzero__"): pass'
100000 loops, best of 3: 2.23 usec per loop

这些时序结果显示在hasattr()情况下,引发异常的速度很慢,但执行测试比不引发异常要慢。 因此,就运行时间而言,使用异常来处理异常情况是有道理的。

编辑:命令行选项-n将默认为足够大的计数,以便运行时间有意义。 手册中引用

如果没有给出-n,则通过尝试10的连续幂来计算合适数量的环,直到总时间至少为0.2秒。

我也是一个蟒蛇初学者。 虽然我不能说为什么Exception处理在该答案的上下文中被称为便宜,但这是我的想法:

请注意,使用if-elif-else检查每次都必须评估条件。 异常处理(包括搜索异常处理程序)仅在异常情况下发生,这在大多数情况下可能很少见。 这是明显的效率提升。 正如Jay指出的那样,当密钥缺失的可能性很高时,最好使用条件逻辑而不是异常。 这是因为如果在大多数情况下密钥不存在,则不是特殊情况。

也就是说,我建议你不要担心效率而是担心意义。 使用异常处理来检测异常情况并在您想要确定某些内容时检查条件。 昨天我被提醒有关S.Lott意义的重要性。

例证:

def xyz(key):
   dictOb = {x:1, y:2, z:3}
   #Condition evaluated every time
   if dictOb.has_key(key):  #Access 1 to dict
        print dictOb[key]  #Access 2

#Exception mechanism is in play only when the key isn't found.
def xyz(key):
   dictOb = {x:1, y:2, z:3}
   try:
        print dictOb[key]  #Access 1
   except KeyError:
        print "Not Found"

总的来说,有一些处理某些东西的代码,比如缺少密钥, 以防万一需要异常处理,但是在大多数情况下密钥不存在的情况下,你真正想做的是确定密钥是否是present => if-else。 Python强调并鼓励说出你的意思。

为什么例外优于if-elif - >

  1. 当你在你的代码中寻找异常又名异常/意外情况时,它会更清楚地表达意义。
  2. 它更清洁,更具可读性。
  3. 它更灵活。
  4. 它可以用来编写更简洁的代码。
  5. 避免很多讨厌的检查。
  6. 它更易于维护。

注意当我们避免使用try-except时,会继续引发异常。 未处理的异常只是转到默认处理程序。 当您使用try-except时,您可以自己处理错误。 它可能更有效,因为if-else需要条件评估,而寻找异常处理程序可能更便宜。 即使这是真的,它的收益也会太小而无法考虑。

我希望我的回答有所帮助。

什么是静态与动态调用和返回,以及为什么您认为Python中的调用和返回有任何不同,具体取决于您是否在try / except块中执行此操作? 即使您没有捕获异常,Python仍然必须处理可能引发某些事情的调用,因此对于如何处理调用和返回,它对Python没有任何影响。

Python中的每个函数调用都涉及将参数推送到堆栈,并调用callable。 每个函数终止后跟调用者,在Python的内部连接中,检查成功或异常终止,并相应地处理它。 换句话说,如果你认为当你在一个try / except块时有一些额外的处理,当你不在一个块中时,它会以某种方式跳过,你就错了。 我认为这就是你“静态”与“动态”区别的关键所在。

此外,这是一个风格问题,经验丰富的Python开发人员开始阅读异常捕获,因此当他们看到适当的try / except调用时,它比条件检查更具可读性。

正如S.Lott所说,一般的信息是,try / except 不会受到伤害,所以你应该在适当的时候随意使用它。

这场辩论通常被称为“LBYL vs EAFP” - 即“在你跳跃之前看”与“比允许更容易请求宽恕”。 Alex Martelli在这里讨论了这个主题: http//mail.python.org/pipermail/python-list/2003-May/205182.html这个辩论差不多六年了,但我不认为基本问题有变化很大。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM