Python中零错误的好处
假设我有两个变量x&y,可以是任何值。我得把x除以y。y可以是零。现在我有两种方法 (一) (二)Python中零错误的好处,python,Python,假设我有两个变量x&y,可以是任何值。我得把x除以y。y可以是零。现在我有两种方法 (一) (二) 我的问题是,方法2是否比方法1有任何好处,如果是,那么它是什么?从性能角度来看,我想说,选项2是否比选项1有任何好处取决于y为0的频率 如果y为0是常见的,那么选项2就不太可取,因为它最终会非常频繁地引发零分错误,而在y==0时执行操作:或如果y!=0:检查将节省时间 但是,如果y很少为0(这是一个例外情况),那么选项2会更可取,因为您不会有执行if检查的开销,并且只会很少出现错误 计时示例- I
我的问题是,方法2是否比方法1有任何好处,如果是,那么它是什么?从性能角度来看,我想说,选项2是否比选项1有任何好处取决于
y
为0的频率
如果y
为0是常见的,那么选项2就不太可取,因为它最终会非常频繁地引发零分错误,而在y==0时执行操作:
或如果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
块性能更好
基本上,例外情况应该适用于例外情况。
尝试
/除了可能的例外
一般来说,“Pythonic方式”是尝试做您想做的事情,如果错误不起作用,则处理它(“”),而不是预先检查(“”),以便在将来提供更多的灵活性
似乎y
通常是代码中的整数(例如int
)。。但是,假设您的需求不断发展,y
是NewClass
的一个实例,现在可以保存一个类似-0.0001
的值
为了保持与应用程序的兼容性,NewClass.\uuuu eq\uuu()
的编写方式是,如果y==0,则将进行整数比较(即在本例中为True
),但NewClass.\uu truediv\uuu
使用浮点值,因此1/y
不会返回错误
因此,如果您使用if
,您的应用程序将像-0.0001==0
一样运行,而使用除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
参见vs.a/b+c/d+e/f+g/h
的示例。琐碎的例子不一定能教给我们好的实践。我发现的数字表明,try
/除了
比如果
稍微快一点,(而且,“alot”并不意味着你认为它能做什么…)我不是说try/except
不好,只是它基本上取决于具体情况。例外情况适用于例外情况。@AnandSKumar在Python中,我不同意-EAFP通常优于LBYL。这是一个具体的数值例子,但我也更喜欢LBYL,因为它生成的代码比捕获异常更能表达算法。除了最初的问题是关于一次性的,而不是在多次迭代中可能会引发异常的紧密循环。Re@deets“具体的数字案例”,不一定那么明确——见我的答案。
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
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