我构建了这两段代码,我想知道哪些是“更好”。由此我不一定意味着哪一个更快执行,因为这不是我的程序的关注。哪一个更具可读性?
或者:
A = 1
B = some_other_value
try:
A /= B
except ZeroDivisionError:
pass
或者:
A = 1
B = some_other_value
if B != 0:
A /= B
答案 0 :(得分:2)
第二个可能更具可读性,但第一个允许更大的多态性和鸭子类型(在B不是float
或int
的情况下,但是支持除法的对象)。
此处的大多数讨论似乎都忽略了 B
可能支持分组的自定义对象。考虑以下以NumType
类作为分母的exapmles。
>>> 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
答案 1 :(得分:1)
当然第二个:
A = 1
B = some_other_value
if B != 0:
A /= B
不是因为它更具可读性,而是因为你没有在异常条件下使用异常。如果在正常情况下可能出现无效输入或可能导致错误的输入,那么您绝不应该使用异常来处理它。
你可以在网上找到关于这方面的非常好的解释,但在我看来(除了表现)总是因为意图:当你处理异常时,你会向读者清楚说明它是<强>异常情况,这是一个错误,在正常的程序流程中不应该发生。在您的情况下不是因为无效输入是绝对可能的(必须始终验证每个输入)。
从我的角度来看,你想要处理它的事实意味着它是可能的,然后检查始终是正确的解决方案。就像Ryan所说,如果你不必检查零,你可能有更高的多态性,那么你要做的就是将检查移动到可以处理这种情况的地方(例如在/运算符中,而不是在你使用它的地方) )。
修改强>
几句话更总结我写的评论。 Python鼓励一种名为EAFP的编程风格,当你编写小脚本时,这是一个很好的资源,但在编写应用程序和库时应该小心使用它。
有助于保持代码简短(并且快速用于最常见的代码路径),但它有一个大劣势:如果你不喜欢要包含try
/ execpt
每一行,你必须处理中间结果和部分计算。一个大的try
可能会使应用程序处于不确定状态(或者它只会使您的代码更不易读,因为很长的列表 - 可能是嵌套的 - try
/ except
/ {{1 }} / else
)。
我同意在您甚至没有想到的情况下使用您的代码会有所帮助,但不灵活,脆弱。对于一个简短的个人脚本可能没问题但是如果我编写一个应用程序(或者更多的是一个库)我想确定我的代码在哪里以及如何失败,我会编写测试来检查它是如何工作的不同输入。我不希望它以我无法预测的方式失败,意外输入&gt;意外行为听起来太像垃圾输入&gt;垃圾输出。应用程序必须健壮。在检查了所有可以查看的内容之后,您甚至必须为特殊情况做好准备(我可以放松这个规则,以便在极少数情况下检查可能是偏执的。)
答案 2 :(得分:0)
答案是:这取决于。
是否可以轻松编写适当的测试来处理条件。在这种情况下,你可以。
另一个考虑因素是您的手写测试是否足够。在一行代码中,这很容易。如果你有许多操作,那么假设一切都很好可能更有意义,并在事后用异常来解决。 (当然,在这种情况下,输入验证通常可能更有用)。
与编程中的大多数事情一样,这是风格和品味的问题。在python中尤其如此,它通常有多种处理方式(尽管你可能已阅读过任何复活节彩蛋),并且主要基于程序员能够做出自己决定的想法(不像Java,确实尝试强制执行单一的编程风格,通过使一切意外变得比预期的技术更难和更令人不愉快。
想想你在做什么以及为什么。尽量不要重复自己。