我在前面的回答中读到异常处理在Python中很便宜所以我们不应该进行预条件检查.
我以前没有听说过这个,但我对Python比较陌生.异常处理意味着动态调用和静态返回,而if
语句是静态调用,静态返回.
如何做好检查是坏的,try-except
好的,似乎是另一种方式.谁可以给我解释一下这个?
不要出汗小东西.您已经选择了一种较慢的脚本语言,因此尝试优化操作码并不会对您有所帮助.选择像Python这样的解释型动态语言的原因是为了优化你的时间,而不是CPU.
如果您使用通用语言惯用语,那么您将看到快速原型设计和干净设计的所有好处,并且随着新版本的Python发布和计算机硬件升级,您的代码将自然运行得更快.
如果您遇到性能问题,请分析您的代码并优化慢速算法.但同时,在特殊情况下使用异常,因为它会使你最终在这些方面做的任何重构变得容易多了.
您可能会发现这篇文章很有用:尝试/除了Python中的性能:一个简单的测试,其中Patrick Altman做了一些简单的测试,以查看在条件前检查的各种场景中的性能(在这种情况下特定于字典键)并仅使用例外.如果您想要调整代码以测试其他条件,也会提供代码.
他得出的结论是:
从这些结果来看,我认为快速确定一些结论是公平的:
如果该元素很可能不存在,那么最好用has_key检查它.
如果你提出异常,你不会对异常做任何事情,那么你最好不要让一个人拥有除外
如果元素可能存在,那么使用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秒.