I am trying to create a user defined exception in the below quadratic roots program (using classes).
The intention is to throw and error back if the input list length is not 3 (need 3 inputs for the 3 coefficients). Additionally, I would want the code to stop executing if there is an input error.
However, this code isn't working, it doesn't throw an exception and the code continues to execute.
Would greatly appreciate if you could guide me.
class quadRoots():
def __init__(self,coeff):
self.A = coeff[0]/coeff[0]
self.B = coeff[1]/coeff[0]
self.C = coeff[2]/coeff[0]
self.Z = 0
self.R_1 = 0
self.R_2 = 0
self.coeff = len(coeff)
try:
self.coeff == 3
except:
print("Input size is not valid")
def roots(self):
import cmath
self.Z = cmath.sqrt((self.B**2)/4 - (self.C))
self.R_1 = ((-(self.B)/2) + self.Z)
self.R_2 = ((-(self.B)/2) - self.Z)
return [self.R_1,self.R_2]
def mult(self):
return quadRoots.roots(self)[0] * quadRoots.roots(self)[1]
def sumRoots(self):
return [complex(-(self.B))]
def prodRoots(self):
return [complex(self.C)]
quadroots([1,-9,14,15]).roots()
try:
self.coeff == 3
except:
print("Input size is not valid")
A Try-Except Chain doesn't work like this. It works when there is an error. But here, there is no error. I suggest you use assert self.coeff == 3, "Input size is not valid". instead, it raises an error, and exits the program, if self.coeff is not equal to 3.
so then the whole try except chain can be replaced by one line. assert self.coeff == 3, "Input size is not valid"
Related
I am running my script in Flask and to catch and print the errors on the server I have made functions that either return None if succeeded else return an error message.
The problem is I have many functions which runs one after another and uses global variable from earlier function, this makes the code unorganized. What can I do?
App.py
from flask import Flask
from main import *
app = Flask(__name__)
#app.route('/')
def main():
input = request.args.get('input')
first_response = function1(input)
if first_response is None:
second_response = function2() # no input from hereon
if second_response is None:
third_response = function3() # functions are imported from main.py
if third_response is None:
...
if ...
else ...
else:
return third_response
else:
return second_response
else:
return first_response
main.py
def function1(input):
global new_variable1
if input is valid:
new_variable1 = round(input,2)
else:
return "the value is not integer"
def function2():
global new_variable2
if new_variable1 > 8:
new_variable2 = new_variable1 / 8
else:
return "the division is not working, value is 0"
def function3():
...
This is just a demo of what's going on. The last function will return a value either side. So if everything goes right I would be able to see the right output as well as I will see error on any given function.
The code works fine, but I need better alternative to do this.
Thanks!
Ah...you have (correctly) determined that you have two things to do:
Process your data, and
Deal with errors.
So let's process the data replacing global with parameteters (and come back to the error handling in a bit). You want to do something like this.
main.py
def function1(some_number):
if some_number is valid:
return round(some_number, 2)
def function2(a_rounded_number):
if a_rounded_number > 8:
return a_rounded_number / 8
So each function should return the results of its work. Then the calling routine can just send the results of each function to the next function, like this:
app.py
# [code snipped]
result1 = function1(the_input_value)
result2 = function2(result1)
result3 = function3(result2)
But...how do we deal with unexpected or error conditions? We use exceptions, like this:
main.py
def function1(some_number):
if some_number is valid:
return round(some_number, 2)
else:
raise ValueError("some_number was not valid")
and then in the calling routine
app.py
try:
result1 = function1(some_input_value)
except (ValueError as some_exception):
return str(some_exception)
Here is a piece of my code:
def main():
num = 0
try:
raise Exception('This is the error message.')
except Exception:
num += 1
return num
finally:
num += 1
a = main()
print(a)
The returning value is 1 instead of 2, this does not make a lot of sense for me.
I thought it would return 2 since finally should execute before returning the value.
Can someone help me to understand this?
You're running into the difference between an identifier and a value. num += 1 is creating a new int object and assigning the num identifier to point to it. It does not change the int object the identifier is already pointing to. (For small values the int objects are cached but that's an implementation detail)
You can see the difference with an operation that does mutate the object in the below code:
def y():
l = []
try:
raise Exception
except Exception:
print("except")
l.append(1)
return l
finally:
print("finally")
l.append(2)
print(y())
# except
# finally
# [1, 2]
The finally is executed (this is clearly defined in the documentation), but as you return an immutable object, the modification is unseen as your returned name is now part of a different scope.
This would work as you expect with a mutable object, for instance a list:
def main():
lst = [0]
try:
raise Exception('This is the error message.')
except Exception:
lst[0] += 1
return lst
finally:
lst[0] += 1
a = main()
print(a)
Output: [2]
The finally block does execute before returning the value, but the return value has already been computed.
return num evaluates num, getting 1, then the finally block starts. The finally block increments num, but the return value has already been evaluated, so it doesn't matter. At the end, the 1 computed earlier is returned.
It's because you are returning in except block
Using return word will end code execution in this function.
To avoid it you could write like this:
def main():
num = 0
try:
raise Exception('This is the error message.')
except Exception:
num += 1
finally:
num += 1
return num
a = main()
print(a)
I want to write a function that check a condition (with custom exceptions) and if no exceptions are raised it applies a function and return the result.
# Custom exceptions
class NegativeNumber(Exception):
pass
class BigNumber(Exception):
pass
def add_two(number):
return number + 2
def apply_function(number, f):
def check_condition(number, f):
try:
if number < 0:
raise NegativeNumber
if number > 10:
raise BigNumber
except NegativeNumber:
return ("Negative Number")
except BigNumber:
return ("Big Number")
return (f(number))
return check_condition(number, f)
apply_function(5, add_two)
Can be this code written better using decorators?
You've already done most of it. I modified your function name and the structure of your code a bit. This should be what you are looking for:
# Custom exceptions
class NegativeNumber(Exception):
pass
class BigNumber(Exception):
pass
def check_exceptions(f):
def wrapped(number):
try:
if number < 0:
raise NegativeNumber
if number > 10:
raise BigNumber
except NegativeNumber:
return "Negative Number"
except BigNumber:
return "Big Number"
return f(number)
return wrapped
#check_exceptions
def add_two(number):
return number + 2
for num in (-1, 5, 15):
print(add_two(num))
Output:
Negative Number
7
Big Number
I wrote a code to catch my error message using try and except (I want to write it without using isinstance) and I am getting the error message when the input is not an integer. The problem is, the program is giving me error message even if the input is valid integer. Please give me some suggestions to make it run. My code is given below:
I tried using exception clause but that did not work.
class Hotel:
def __init__(self,room,catagory):
if room != int:
raise TypeError ()
self.room = room
self.catagory = catagory
self.catagories = {"A":"Elite","B":"Economy","C":"Regular"}
self.rooms = ["0","1","2","3","4","5"]
def getRoom(self):
return self.room
def getCatagory(self):
return self.catagory
return self.catagories.get(self.catagory)
def __str__(self):
return "%s and %s"%(self.rooms[self.room],self.catagories.get(self.catagory))
try:
room1 = Hotel(a,"A")
room2 = Hotel(1,"A")
print(room1.getRoom())
except:
print("there's an error")
I am expecting:
there's an error
1 and Elite
A
You are checking if room != int . It will give you error always.
You have to check type(room)!= int .
I have corrected the code below
class Hotel:
def __init__(self,room,catagory):
if type(room) != int:
raise TypeError ()
self.room = room
self.catagory = catagory
self.catagories = {"A":"Elite","B":"Economy","C":"Regular"}
self.rooms = ["0","1","2","3","4","5"]
Is there better way of writing this code:
def add (exe1, exe2):
try:
a = float (exe1)
b = float (exe2)
total = float (a + b)
except ValueError:
return None
else:
return total
You can have it all inside a try/except block (calculation and return):
def add(exe1, exe2):
try:
return float(exe1) + float(exe2)
except ValueError:
return None
Also note, the default return value from function is None, so the second return is not really necessary (you could have pass instead), but it makes code more readable.
You can also use contextlib.suppress, if you find it more readable.
from contextlib import suppress
def add(exe1, exe2):
with suppress(ValueError):
return float(exe1) + float(exe2)
See the documentation here.