"""Lecture 24 examples: exceptions.""" from ucb import main, interact, trace def assert_false(): assert False, 'False!' def invert(x): """Return 1/x >>> invert(2) Never printed if x is 0 0.5 """ result = 1/x # Raises a ZeroDivisionError if x is 0 print('Never printed if x is 0') return result def invert_safe(x): """Return 1/x, or the string 'divison by zero' if x is 0. >>> invert_safe(2) Never printed if x is 0 0.5 >>> invert_safe(0) 'division by zero' """ try: return invert(x) except ZeroDivisionError as e: return str(e) # Robust iterative improvement class IterImproveError(Exception): def __init__(self, last_guess): self.last_guess = last_guess def iter_improve(update, done, guess=1, max_updates=1000): """Iteratively improve guess with update until done is true.""" k = 0 try: while not done(guess) and k < max_updates: guess = update(guess) k = k + 1 return guess except ValueError: raise IterImproveError(guess) def find_root(f, guess=1): """Return a guess of a zero of the function f, near guess. >>> from math import sin, sqrt >>> find_root(lambda y: sin(y), 3) 3.141592653589793 >>> find_root(lambda x: 2*x*x + sqrt(x)) -0.030211203830201594 """ def done(x): return f(x) == 0 try: return iter_improve(newton_update(f), done, guess) except IterImproveError as e: return e.last_guess def approx_derivative(f, x, delta=1e-5): """Return an approximation to the derivative of f at x.""" df = f(x + delta) - f(x) return df/delta def newton_update(f): """Return an update function for f using Newton's method.""" def update(x): return x - f(x) / approx_derivative(f, x) return update # Exception chaining (bonus material) class E(Exception): """An exception class.""" class F(Exception): """Another exception class.""" def handle_f(): try: raise F except F as f: raise E from f @main def run(): interact()