-1

我已经构建了这两段代码,我想知道哪个“更好”。我并不一定意味着哪个执行得更快,因为这不是我的程序关心的问题。哪个更具可读性?

任何一个:

A = 1
B = some_other_value
try:
    A /= B
except ZeroDivisionError:
    pass

或者:

A = 1
B = some_other_value
if B != 0:
    A /= B
4

3 回答 3

2

第二个可能更具可读性,但第一个允许更大的多态性和鸭子类型(在 B 不是floator 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
于 2013-07-01T16:13:21.277 回答
1

当然是第二个:

A = 1
B = some_other_value
if B != 0:
    A /= B

不是因为它更具可读性,而是因为您没有对非异常情况使用异常。如果在正常情况下可能出现无效输入或可能导致错误的输入,那么您永远不应该使用异常来处理它。

你可以在网上找到很好的解释,但在我看来(除了性能之外)总是因为意图:当你处理异常时,你会向读者明确这是一个异常情况,一个错误,不应该发生的事情在正常的程序流程中。在您的情况下,这并不是因为绝对可能出现无效输入(必须始终验证每个输入)

从我的角度来看,您想要处理它意味着这是可能的,那么检查始终是正确的解决方案。就像 Ryan 说的那样,如果你不必检查零,你可能有更高的多态性,那么你要做的就是将检查移到你可以处理这种情况的地方(例如在 / 运算符中,而不是在你使用它的地方)。

编辑
几句话来总结我写的评论。Python 鼓励一种称为 EAFP 的编程风格,当您编写小脚本时,这是一个很好的资源,但在您编写应用程序和库时应谨慎使用。

它有助于保持代码简短(并且对于最常见的代码路径来说快速),但它有一个很大的缺点:如果你不换行try/execpt每几行你将不得不处理中间结果和部分计算。大的try可能会使应用程序处于不确定状态(或者它只会使您的代码的可读性大大降低,因为一长串 - 可能是嵌套的 - try/ except/ else/ finally)。

我同意在您甚至没有考虑过的情况下使用您的代码会有所帮助,但这不是灵活性,而是脆弱性。一个简短的个人脚本可能没问题,但是如果我编写一个应用程序(或者,甚至更多,一个库),我想确定我的代码在哪里以及如何失败,我将编写测试来检查它如何与不同的输入一起工作. 我不希望它以我无法预测的方式失败,意外输入 > 意外行为听起来太像垃圾输入 > 垃圾输出。应用程序必须是健壮的。在你检查了所有你可以检查的东西之后,你甚至必须为特殊情况做好准备(对于非常罕见的情况,我可能会放宽这条规则,以至于检查可能是偏执的)。

于 2013-07-01T16:12:28.617 回答
0

答案是:视情况而定。

考虑是否可以轻松编写适当的测试来处理条件。在这种情况下,您可以。

另一个考虑因素是您的手写测试是否足够。在一行代码中,这很容易。如果您进行了许多操作,那么假设一切都很好,然后排除异常可能会更有意义。(当然,在这种情况下,输入验证通常可能更有用)。

与编程中的大多数事情一样,这是风格和品味的问题。在 python 中尤其如此,它通常有多种做事方式(尽管您可能已经阅读过任何复活节彩蛋),并且很大程度上基于程序员能够做出自己的决定的想法(不像 Java,它确实试图通过使所有意想不到的事情比预期的技术更难、更不愉快来强制执行单一的编程风格)。

想想你在做什么以及为什么。尽量不要重复自己。

于 2013-07-01T16:32:59.127 回答