CS30 - Spring 2015 - Class 11

Example code in this lecture

   exceptions.py

Lecture notes

  • administrative
       - assignment 5 out
          - part A due on Tuesday (start working on it after the midterm!)
       
       - midterm Thursday
          - review session in lab tomorrow
          - can bring notes up to 4 pages (single sided)

  • What inputs to the calc_prob_attempt function in exceptions.py code would cause an error?
       - if trials = 0, then we get a divide by zero, e.g.

          >>> calc_prob_attempt(10, 0)
          Traceback (most recent call last):
           File "/Applications/Wing101.app/Contents/Resources/src/debug/tserver/_sandbox.py", line 1, in <module>
           # Used internally for debug sandbox under external interpreter
           File "/Applications/Wing101.app/Contents/Resources/src/debug/tserver/_sandbox.py", line 2, in calc_prob_attempt
           if __name__ == '__main__':
          ZeroDivisionError: float division by zero

       - if successes or trials is not a number, e.g.
          >>> calc_prob_attempt("bananas", 10)
          Traceback (most recent call last):
           File "/Applications/Wing101.app/Contents/Resources/src/debug/tserver/_sandbox.py", line 1, in <module>
           # Used internally for debug sandbox under external interpreter
           File "/Applications/Wing101.app/Contents/Resources/src/debug/tserver/_sandbox.py", line 2, in calc_prob_attempt
           if __name__ == '__main__':
          ValueError: could not convert string to float: bananas

          >>> calc_prob_attempt(10, "bananas")
          Traceback (most recent call last):
           File "/Applications/Wing101.app/Contents/Resources/src/debug/tserver/_sandbox.py", line 1, in <module>
           # Used internally for debug sandbox under external interpreter
           File "/Applications/Wing101.app/Contents/Resources/src/debug/tserver/_sandbox.py", line 2, in calc_prob_attempt
           if __name__ == '__main__':
          TypeError: unsupported operand type(s) for /: 'float' and 'str'

  • How can we fix these?
       - the divide by zero problem we can check using an if-else statement
       - checking the type is harder...

  • checking the type of a variable
       - isinstance
          - takes two parameters
          - a value
          - a type
          - and returns true if the value is of that type

          >>> isinstance("banana", str)
          True
          >>> isinstance("banana", int)
          False
          >>> isinstance(10/2, int)
          True
          >>> isinstance([1, 2, 3], list)
          True
          >>> isinstance(10 + 2, list)
          False
          >>> isinstance(10 + 2, int)
          True

       - look at the calc_prob_better function in exceptions.py code
          - we check to make sure that both successes and trials are ints and print an error if they're not
          - we could probably allow successes to be a float if we wanted...

  • exception/error handling
       - to check for divide by zero, we could use an if statement, but there's another way
       - try-except blocks allow us to handle errors that may be produced in code we're writing
          - the format is

          try:
             # some code that
             # might result in
             # an error
          except:
             # code to be run
             # if an error
             # occurs

          # some more code
       
       - python executes the statements in the "try" block
          - if an error does NOT occur, then the code is executed normally, the code in the "except" block is skipped and the program continues on after the try-except block
          - if an error DOES occur, then the remaining code in the try part of the block is skipped and the program executes the statements in the "except" block, then continues on after the try-except block

       - For example, look at the calc_prob_even_better function in exceptions.py code
          - if an error occurs in "float(successes)/trials" then an error message will be printed

  • handling specific errors
       - the generic try-catch block will catch/handle ANY exception that occurs in the "try" part of the block
       - sometimes, we just want to handle specific errors. In this case, we can optionally specify the error:

          try:
             # some code that
             # might result in
             # an error
          except (name_of_the_error):
             # code to be run
             # if name_or_the_error
             # occurs

          # some more code

          - if the name error occurs in the try part of the block, then it will be handled
          - if an error occurs, but it's not of that type, then it will still be reported as an error and the program will stop

       - the calc_prob function in exceptions.py code only handles the the ZeroDivisionError

          >>> calc_prob(10, 0)
          trials must be non-zero!
          >>> calc_prob("banana", 10)
          calc_prob_better must be called with ints!

  • multiple except blocks
       - we may want to handle different exceptions in different ways
       - for a given try block we can have multiple except blocks
          
          try:
             # some code that
             # might result in
             # an error
          except (name_of_the_error):
             # code to be run
             # if name_of_the_error
             # occurs
          except (other_error):
             # code to be run
             # if other_error
             # occurs
          except:
             # code to be run if
             # any other error occurs

       - if an error occurs, python checks each except block starting from the top to see if it matches
       
       - calc_prob2 in exceptions.py code is another version that only uses error handling
          - if a divide by zero occurs, then "trials must be non-zero" will be printed
          - if any other error occurs (e.g. wrong types passed in), then the generic message will be printed

          >>> calc_prob2(10, 0)
          trials must be non-zero!
          >>> calc_prob2("banana", 10)
          calc_prob_better had a problem :(

       - if we comment out:

          except:
           print "calc_prob2 had a problem :("

          and run the same inputs:

          >>> calc_prob2(10, 0)
          trials must be non-zero!
          >>> calc_prob2("banana", 10)
          Traceback (most recent call last):
           File "/Applications/Wing101.app/Contents/Resources/src/debug/tserver/_sandbox.py", line 1, in <module>
           # Used internally for debug sandbox under external interpreter
           File "/Applications/Wing101.app/Contents/Resources/src/debug/tserver/_sandbox.py", line 32, in calc_prob2
          ValueError: could not convert string to float: banana

          we see only the divide by zero being handled