我构建了这两个代码,我想知道哪个更好。由于这不是我的程序所关心的,所以我并不一定意味着哪一个更快执行。哪一个更具可读性?Python:哪个代码更好?
或者:
A = 1
B = some_other_value
try:
A /= B
except ZeroDivisionError:
pass
或者:
A = 1
B = some_other_value
if B != 0:
A /= B
我构建了这两个代码,我想知道哪个更好。由于这不是我的程序所关心的,所以我并不一定意味着哪一个更快执行。哪一个更具可读性?Python:哪个代码更好?
或者:
A = 1
B = some_other_value
try:
A /= B
except ZeroDivisionError:
pass
或者:
A = 1
B = some_other_value
if B != 0:
A /= B
当然第二个:
A = 1
B = some_other_value
if B != 0:
A /= B
不是因为它更具可读性,但因为你没有使用一个例外非特殊情况。如果无效输入或在正常情况下可能导致错误的输入是可能的,那么您绝不应该使用异常来处理它。
你可以找到(旁边性能)关于这个网络上,但在我看来很不错的解释总是因为意图的:当你处理异常,那么你明确地告诉读者,这是一个异常情况,一个错误,这在正常的程序流程中不应该发生。在你的情况这不是因为一个无效的输入是绝对可能的(每个输入必须被验证,总是)。
从我的角度来看,你想要处理它的事实意味着这是可能的,然后检查总是正确的解决方案。就像Ryan所说的,如果你不需要检查零值,你可能会有更高的多态性,那么你需要做的是移动支票来处理这种情况(例如在/运算符中,而不是在你使用它的地方)。
编辑
很少有词汇可以总结我写的评论。 Python鼓励一种名为EAFP的编程风格,当你编写小脚本时,这是一个很好的资源,但在编写应用程序和库时应该谨慎使用它。
它有助于保持码短(和快速为最常见的代码路径),但它有一个大缺点:如果你不try
/execpt
包装每个几行你会必须处理中间结果和部分计算。一个大的try
可能会使应用程序处于不确定状态(否则它会使您的代码更不易读,因为长列表可能是嵌套的 - try
/except
/else
/finally
)。
我同意它有助于使用你的代码的情况下,你甚至没有去想但这不灵活,这是脆弱。对于简短的个人脚本也许可以,但是如果我编写一个应用程序(或者甚至更多的库),我想确定我的代码在哪里以及如何失败,我会编写测试以检查它如何与不同的输入一起工作。我不希望它会以我无法预知的方式失败,意外的输入>意外的行为听起来太像垃圾输入>垃圾输出。应用程序必须健壮。在你检查完你可以检查的所有东西之后,你甚至必须为异常情况做好准备(我可以放松这个规则,以便检查可能是偏执的)。
除以零并不例外? –
@HunterMcMillen **不,它不是**,因为输入必须总是**验证**,特别是如果你认为它可能发生(除了块以外的空白让我认为他们必须是)。 –
@Adriano EAFP更加pythonic,输入验证通常是不鼓励的。而且你需要在此之上进行类型测试来实际验证输入,这很少被鼓励。 –
第二个可能更具可读性,但第一个允许更大的多态性和鸭子打字(在B不是float
或int
,但是支持除法的对象)的情况下。
大多数讨论在这里似乎是缺少点是B
可能是支持部门自定义对象。请考虑下面的例子,其中NumType
作为分母。
>>> class NumType(object): # basically, an int wrapper
... """Custom number type. Supports division when it is the denominator"""
... def __init__(self, val):
... self.val = val
... def __rdiv__(self, num):
... return num/self.val
...
>>> c = NumType(1) #normal division works as expected
>>> 5/c
5
>>> c = NumType(7)
>>> 5./c
0.7142857142857143
>>> c = NumType(0)
>>> 5/c # 0 division causes exception
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in __rdiv__
ZeroDivisionError: integer division or modulo by zero
>>> # pay attention here:
>>> if c != 0: # condition is True because c is an object, not 0
... print 5/c # so this division still occurs, and generates an exception
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "<stdin>", line 5, in __rdiv__
ZeroDivisionError: integer division or modulo by zero
>>> # however, this is caught with a try/except
>>> try:
... 5/c
... except ZeroDivisionError:
... print '0 division'
...
0 division
答案是:取决于。
您是否可以轻松编写适当的测试来处理条件。在这种情况下,你可以。
另一个考虑因素是你的手写测试是否足够。在一行代码中,这很容易。如果你有很多操作,假设一切都很好,并且事后弄清楚,例外情况可能更有意义。 (当然,在这种情况下,输入验证通常会更有用)。
与编程中的大多数事情一样,这是风格和品味的问题。在python中尤其如此,python通常具有多种处理方式(尽管你可能已经阅读过任何复活节彩蛋),而且它主要基于程序员能够做出自己的决定的想法(不像Java,确实试图强制执行一种编程风格,通过使所有事情都比预期的技术更难以且更令人不快)。
想想你在做什么,为什么。尽量不要重复自己。
**既不是**,因为这两个代码位有效地隐藏了计算出现问题的事实。 –
重复的:http://stackoverflow.com/questions/1835756/using-try-vs-if-in-python – Wessie
python使用异常流控制的事实并不意味着你应该只使用异常流控制。 – mishik