Example: raising an exception
def get_ratios(L1, L2): """ Assumes: L1 and L2 are lists of equal length of numbers Returns: a list containing L1[i]/L2[i] """ ratios = [] for index in range(len(L1)): try: ratios.append(L1[index]/L2[index]) except ZeroDivisionError: ratios.append(float('nan')) #nan = not a number except: raise ValueError('get_ratios called with bad arg') #manage flow of program by raising own error return ratios get_ratios("") #will raise ValueError. Can enclose this within an except blockNotice that an exception searches for the innermost
try/except
block. If it does not exist in the
current function, it exits the function (destroying its scope) and going to the caller's scope, caller's caller's scope,
and so on, until a try/except
block is found. If no try/except
block is found, the program terminates and the user is shown the details of the exception raised.
Example: We are given a class list for a subject, such that each list entry is a list of two parts:
marks = [ [ ['rahul', 'tendulkar'], [80.0, 70.0, 85.0] ], [ ['sachin', 'dravid'], [100.0, 80.0, 74.0] ] ]Create a new class list, with name, marks, and an average
[ [ ['rahul', 'tendulkar'], [80.0, 70.0, 85.0], 78.33333 ], [ [ 'sachin', 'dravid'], [100.0, 80.0, 74.0], 84.66667 ] ]
Example code
def get_stats(class_list): new_stats = [] for elt in class_list: new_stats.append([elt[0], elt[1], avg(elt[1])]) return new_stats def avg(marklist): return sum(marklist)/len(marklist)
We will get an error on the following input:
marks = [ [ ['rahul', 'tendulkar'], [80.0, 70.0, 85.0] ], [ [ 'sachin', 'dravid'], [100.0, 80.0, 74.0] ], [ ['test'], [] ] ]Get
ZeroDivisionError: float division by zero
because try to divide by len(marklist)
which
is 0
for test
.
Multiple choices for handling these errors using except
:
None
value.
def avg(marklist): try: return sum(marklist)/len(marklist) except: print('warning: no marks data')This results in the following output:
warning: no marks data marks = [ [ ['rahul', 'tendulkar'], [80.0, 70.0, 85.0], 78.33333 ], [ [ 'sachin', 'dravid'], [100.0, 80.0, 74.0], 84.66667 ], [ ['test'], [], None ] ]Notice that the
None
value is output because avg
did not return anything in the except
block, which is equivalent to returning the None
value.
0.0
.
def avg(marklist): try: return sum(marklist)/len(marklist) except: print('warning: no marks data') return 0.0This results in the following output:
warning: no marks data marks = [ [ ['rahul', 'tendulkar'], [80.0, 70.0, 85.0], 78.33333 ], [ [ 'sachin', 'dravid'], [100.0, 80.0, 74.0], 84.66667 ], [ ['test'], [], 0.0] ]
def avg(marklist): try: return sum(marklist)/len(marklist) except: print('warning: no marks data') raise ValueError("marklist found empty")This results in the following output:
warning: no marks data Traceback: ... .... ValueError: "marklist found empty"
Assertions
assert
statement to raise an AssertionError
exception if assumptions not met.def avg(marklist): assert len(marklist) != 0, 'no grades data' return sum(marklist)/len(marklist)
AssertionError
if it is given an empty marklist
Assertions as defensive programming
z0_power_i == z0**i
at the beginning the body of a for-loop.Where to use assertions?
n=len(L)
, or z0_power_i == z0**i
at certain program points.Example:
cube = int(input("Enter a number: ") for guess in range(abs(cube)+1): assert(guess**3 <= abs(cube)) if guess**3 >= abs(cube): break assert(guess**3 < abs(cube)) if guess**3 != abs(cube): print(cube, 'is not a perfect cube') else: if cube < 0: guess = -guess print('Cube root of ' + str(cube) + ' is ' + str(guess))Another example:
cube = int(input("Enter a number: ") epsilon = 0.01 low = 0 high = cube guess = (low+high)/2.0 num_guesses = 0 while abs(guess**3 - cube) >= epsilon: assert(low <= guess) assert(guess <= high) if guess**3 < cube: low = guess else: high = guess guess = (high + low)/2.0 num_guesses += 1 print 'num_guesses =', num_guesses print(guess, 'is close to the cube root of', cube)
Example on longest common subsequence (LCS):
def isCommonSubsequence(X, Y, R): xi = 0 yi = 0 for c in R: while X[xi] != c: xi+=1 if xi == len(X): return False while Y[yi] != c: yi+=1 if yi == len(Y): return False return True def lcs(X, Y): ret = "" if len(X) == 0 or len(Y) == 0: ret = "" elif X[-1] == Y[-1]: lcsXY = lcs(X[0:-1], Y[0:-1]) ret = lcsXY + X[-1] else: lcsY = lcs(X[0:-1], Y) lcsX = lcs(X, Y[0:-1]) if len(lcsY) < len(lcsX): ret = lcsX else: ret = lcsY assert(isCommonSubsequence(X, Y, ret)) return ret
Example on placing N queens in an NxN chessboard
global N N = 4 def printSolution(board): for i in range(N): for j in range(N): if board[i][j] == 1: print("Q",end=" ") else: print(".",end=" ") print() def isSafe(board, row, col): # Check this row on left side for i in range(col): if board[row][i] == 1: return False # Check upper diagonal on left side for i, j in zip(range(row, -1, -1), range(col, -1, -1)): if board[i][j] == 1: return False # Check lower diagonal on left side for i, j in zip(range(row, N, 1), range(col, -1, -1)): if board[i][j] == 1: return False return True def solveNQUtil(board, col): # Base case: If all queens are placed # then return true if col >= N: return True # Consider this column and try placing # this queen in all rows one by one for i in range(N): if isSafe(board, i, col): # Place the queen at board[i][col] board[i][col] = 1 # Recurse to place rest of the queens if solveNQUtil(board, col + 1) == True: return True board[i][col] = 0 return False def solveNQ(): board = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] if solveNQUtil(board, 0) == False: print("Solution does not exist") return False for i in range(0, N, 1): for j in range(0, N, 1): assert (!board[i][j] || isSafe(board, i, j)) printSolution(board) return True