假设我有两个变量x& y,可以是任何值。我必须将x除以y。 y可以为零。现在我有两种方法
1)
if y == 0:
continue # or break, supposing there is a loop going on.
2)
try:
print 1/0
except ZeroDivisionError as e:
print e
finally:
print "got"
我的问题是,方法2是否比方法1有任何好处,如果是,那么它是什么?
答案 0 :(得分:2)
try
/ except
可能be slightly faster。
一般来说," Pythonic方式"是尝试做你想做的事情并处理错误,如果它不起作用(" Easier to Ask Forgiveness than Permission"),而不是预先检查(" { {3}}"),以便在将来提供更大的灵活性。
似乎y
通常是代码中的整数(int
的实例)..但想象一下您的需求在不断变化,y
是NewClass
的实例现在可以保存-0.0001
之类的值。
为了保持与您的应用程序的兼容性,编写了NewClass.__eq__()
,以便if y == 0
进行整数比较(即在此实例中为True
),但NewClass.__truediv__
使用浮点值,因此1 / y
不会返回错误。
因此,如果您使用if
,您的应用将采用-0.0001 == 0
,而使用except ZeroDivisionError
则会正确处理新行为。
class NewClass(int):
def __eq__(self, other):
return int(self) == int(other)
def __truediv__(self, other):
return self.value / other
y = NewClass(-0.0001)
if y != 0:
print 1 / y # not printed
try:
print 1 / y # printed
except ZeroDivisionError:
pass
答案 1 :(得分:1)
从绩效的角度来看,我会说选项2是否比选项1有任何好处取决于y
为0的频率。
如果y
为0是常见的,那么选项2将不太可取,因为它最终会频繁地提高ZeroDivisionError,而执行if y == 0:
或if y != 0:
检查会更少耗时。
但是如果y很少为0(这是一个异常情况),那么选项2会更优选,因为你没有进行if
检查的开销,并且很少会引发错误
计时示例 -
In [4]: def func2(lst):
...: for i in lst:
...: try:
...: x = 10/i
...: except ZeroDivisionError:
...: pass
...:
In [5]:
In [5]: def func1(lst):
...: for i in lst:
...: if i != 0:
...: x = 10/i
...:
In [6]: lst1 = [0 for i in range(100)]
In [7]: import random
In [8]: lst2 = [random.randrange(0,5) for i in range(100)]
In [9]: lst3 = [random.randrange(0,15) for i in range(100)]
In [10]: lst2.count(0)
Out[10]: 24
In [11]: lst3.count(0)
Out[11]: 5
In [12]: %timeit func1(lst1)
100000 loops, best of 3: 3.56 µs per loop
In [13]: %timeit func2(lst1)
10000 loops, best of 3: 50.6 µs per loop
In [14]: %timeit func1(lst2)
100000 loops, best of 3: 7.73 µs per loop
In [15]: %timeit func2(lst2)
10000 loops, best of 3: 18 µs per loop
In [16]: %timeit func1(lst3)
100000 loops, best of 3: 8.76 µs per loop
In [17]: %timeit func2(lst3)
100000 loops, best of 3: 9.88 µs per loop
即使只有5%的数字为0,if
循环仍然比try/except
块更高效。
基本上,例外情况应该是特殊情况。