Condition checking vs. Exception handling [duplica

2019-02-08 04:41发布

This question already has an answer here:

When is exception handling more preferable than condition checking? There are many situations where I can choose using one or the other.

For example, this is a summing function which uses a custom exception:

# module mylibrary 
class WrongSummand(Exception):
    pass

def sum_(a, b):
    """ returns the sum of two summands of the same type """
    if type(a) != type(b):
        raise WrongSummand("given arguments are not of the same type")
    return a + b


# module application using mylibrary
from mylibrary import sum_, WrongSummand

try:
    print sum_("A", 5)
except WrongSummand:
    print "wrong arguments"

And this is the same function, which avoids using exceptions

# module mylibrary
def sum_(a, b):
    """ returns the sum of two summands if they are both of the same type """
    if type(a) == type(b):
        return a + b


# module application using mylibrary
from mylibrary import sum_

c = sum_("A", 5)
if c is not None:
    print c
else:
    print "wrong arguments"

I think that using conditions is always more readable and manageable. Or am I wrong? What are the proper cases for defining APIs which raise exceptions and why?

7条回答
叼着烟拽天下
2楼-- · 2019-02-08 05:31

If you're asking, you should probably be using exceptions. Exceptions are used to indicate exceptional circumstances, a specific case where things work differently from other cases. This is the case for prettymuch all errors and for many other things as well.

In your second implementation of sum_, the user has to check every single time what the value was. This is reminiscent of the C/Fortran/other-languages boilerplate (and frequent source of errors) where error codes go unchecked that we avoid. You have to write code like this at all levels to be able to propagate errors. It gets messy and is especially avoided in Python.

A couple other notes:

  • You often don't need to make your own exceptions. For many cases, the builtin exceptions like ValueError and TypeError are appropriate.
  • When I do create a new exception, which is pretty useful, I often try to subclass something more specific than Exception. The built-in exception hierarchy is here.
  • I would never implement a function like sum_, since typechecking makes your code less flexible, maintainable, and idiomatic.

    I would simply write the function

    def sum_(a, b):
        return a + b
    

    which would work if the objects were compatible and if not it would already throw an exception, the TypeError that everyone is used to seeing. Consider how my implementation works

    >>> sum_(1, 4)
    5
    >>> sum_(4.5, 5.0)
    9.5
    >>> sum_([1, 2], [3, 4])
    [1, 2, 3, 4]
    >>> sum_(3.5, 5) # This operation makes perfect sense, but would fail for you
    8.5
    >>> sum_("cat", 7) # This makes no sense and already is an error.
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 1, in sum_
    TypeError: cannot concatenate 'str' and 'int' objects
    

    My code was shorter and simpler yet is more robust and flexible than yours. This is why we avoid typechecking in Python.

查看更多
登录 后发表回答