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 block
Notice 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.0
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'], [], 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 marklistAssertions 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