


Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
This document from williams college covers python exception handling and custom iterators. It explains how exceptions are handled in python using try/except blocks and the importance of catching only what you can handle. The document also discusses the use of the stopiteration class to signal the end of iteration. Additionally, it provides an example of creating a custom iterator for even squares.
Typology: Slides
1 / 4
This page cannot be seen from the preview
Don't miss anything!



By now you’ve probably seen your fair share of Python errors. For example:
l = list(range(10)) l[10] Traceback (most recent call last): File "
", line 1, in IndexError: list index out of range
This IndexError is a Python Exception, which is a way of signaling behavior that is exceptional including errors. Most modern programming languages support exceptions—they allow you to structure your programs so that code to both check and deal with errors is logically distinct from your actual control flow. This makes code much more readable. Here is how exception-handling in Python works. We embed code in a try/except block where, if an exception is raised, the flow immediately jumps to the except clause. If the type of exception matches, then the block is entered. Control flow then returns to the code after the except block. For example, running the follow code
1 l = list(range(10)) 2 try: 3 l[10] 4 except IndexError as ie: 5 print(”Caught an IndexError: {} −− moving on”.format(ie)) 6 7 print(l[0])
produces
Caught an IndexError: list index out of range -- moving on 0
You can use the class hierarchy to catch some types of errors and let others through. For example, above we would only catch exceptions of type IndexError—if we executed the following code
1 l = list(range(10)) 2 try: 3 l.push(5) 4 except IndexError as ie: 5 print(”Caught an IndexError: {} −− moving on”.format(ie))
then the exception would not be caught
Traceback (most recent call last): File "
Errors are actually a good thing: when it comes to exceptions, the rule of thumb is to catch only what you can handle. Consider the portion of the Exception class hierarchy and code example shown below:
BaseException
KeyboardInterrupt Exception
ArithmeticError TypeError
ZeroDivisionError
1 def int fraction(num, denom): 2 try: 3 return num // denom 4 except Exception as e: 5 print(”Can’t divide by zero”) 6 return None
The only exceptional behavior that we can reason about here is dividing-by-zero. However, our except clause catches all exception classes that inherit from the general Exception class. As a result, we do not properly handle the following code:
int_fraction(3, ’a’): Can’t divide by zero None
What we really want is to receive the following error so we know to go back and fix our code:
Traceback (most recent call last): File ‘‘
We would simply change our except clause to catch the specific ZeroDivisionError class.
1 def int fraction(num, denom): 2 try: 3 return num // denom 4 except ZeroDivisionError as e: 5 print(”Can’t divide by zero −− returning 0”) 6 return 0
To cause an error, you simply raise the name of a class that is derived from BaseException. In the next section on iterators, we’ll see how the built-in StopIteration class is used to signal the end of iteration.
Imagine that you wanted to create an iterator that returned squares that were even. One way to do this is to create a new even squares class that inherits from squares. Without any new methods, the even squares class inherits the behavior of squares as is. However, when next is called, we only want even squares returned. To do this, we override the the next method so that it calls the next method of its superclass until it reaches an even square.
1 class EvenSquares(Squares): 2 3 def next (self): 4 sq = super(). next () 5 while (sq % 2 != 0): 6 sq = super(). next () 7 return sq