Exceptions in Python
- At run time, exceptional situations sometimes arise. In Python we can make allowance for them and indicate actions to take. (In contrast assertions should be used for conditions which should never happen.)
One such example is division by zero.
def invert1(n): return 1.0 / n
If we attempt to divide by zero, Python throws a
ZeroDivisionErrorexception.In [1]: invert1(3) Out[1]: 0.3333333333333333 In [2]: invert1(0) --------------------------------------------------------------------------- ZeroDivisionError Traceback (most recent call last) <ipython-input-45-dcd5509b67f7> in <module>() ----> 1 invert1(0) <ipython-input-43-2c7538fe7a03> in invert1(n) 1 def invert1(n): ----> 2 return 1.0/n 3 ZeroDivisionError: float division by zero
We could use
invert1in a function to invert a list of numbers.def invert_list1(alon): return [invert1(n) for n in alon]
However if any of the numbers in the list is zero, Python just throws the exception and stops.
In [3]: list(range(-9, 10)) Out[3]: [-9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9] In [4]: invert_list1(list(range(-9, 9))) --------------------------------------------------------------------------- ZeroDivisionError Traceback (most recent call last) <ipython-input-53-a6f023733ca5> in <module>() ----> 1 invert_list1(list(range(-9, 9))) /home/bon/projects/auc/courses/pyw2014/content/code/exceptions.py in invert_list1(alon) 5 6 def invert_list1(alon): ----> 7 return [invert1(n) for n in alon] 8 9 #---------------------------------------- <ipython-input-43-2c7538fe7a03> in invert1(n) 1 def invert1(n): ----> 2 return 1.0/n 3 ZeroDivisionError: float division by zero
Since it's not uncommon for this to happen when doing numerical calculations, we have a notion of not a number (abbreviated
NaN). It is often used when the result of a numerical calculation is undefined as a float, such as0/0, the various infinities, the square root of a negative number or for missing values.The Python nan is generated by
float('nan').NaNsare contagious; most Python operations on floats returnnanwhen at least one of their arguments is anan. But see the Python manual for special cases.As we have seen, division by zero throws an exception in Python. But we might prefer to return
nanso that we can continue with our calculations:def invert2(n): try: return 1.0 / n except ZeroDivisionError as e: print("Caught a zero:", e) return float("nan")
The Python construct
try..exceptexecutes the code in the first subblock. If that block throws the exception indicated, then that exception is caught and the code in the second block is executed. Any other exception is thrown to top level in the usual way.A
trycan have more than oneexceptand can also havefinallyandelseclauses. See the Python manual for details.We can make a version of
invert_listthat uses thisinvert2def invert_list2(alon): return [invert2(n) for n in alon]
Now we can invert our list without interruption.
In [5]: invert_list2(list(range(-9, 9))) Caught a zero: float division by zero Out[5]: [-0.1111111111111111, -0.125, -0.14285714285714285, -0.16666666666666666, -0.2, -0.25, -0.3333333333333333, -0.5, -1.0, nan, 1.0, 0.5, 0.3333333333333333, 0.25, 0.2, 0.16666666666666666, 0.14285714285714285, 0.125]