I have the below code and when I type calculate(2, 0, "/") I would like to print "Division with zero" than just the output, when I divide with 0. Any suggestions?
def calculate(num1, num2, operator):
if operator == "/" or operator == 'divide':
output = float(num1) / float(num2) if float(num2) else 0
return output
I'd suggest allowing calculate to raise ZeroDivisionError and having the caller print the error:
def calculate(num1, num2, operator):
if operator == "/" or operator == 'divide':
return num1 / num2
try:
print(calculate(2, 0, "/"))
except ZeroDivisionError:
print("Division with zero")
That way you aren't having one function either return or print depending on the situation -- calculate always computes a result (which might include a ZeroDivisionError) without printing it, and the calling code is always in charge of printing it out.
You can simply add an additional condition handling the case you mentioned.
Example:
def calculate(num1, num2, operator):
if num2 == 0 :
print("Division with zero")
return 0
if operator == "/" or operator == 'divide':
output = float(num1) / float(num2)
return output
def main():
calculate(4, 2, "/") # 2
calculate(2, 0, "/") # 0
if __name__ == "__main__":
main()
Related
I'm writing a python script where I find the average of the sum of three numbers. I am using arguments for inputting the numbers. I need to finish the script by printing out error messages.
If I enter something like:
avg3 3 5
avg3 3 4 5 6
avg3 3 one 5
it needs to print an error telling me how to use it.
Here is the start of the script:
def main():
num1 = int(sys.argv[1])
num2 = int(sys.argv[2])
num3 = int(sys.argv[3])
avg = (num1 + num2 + num3)/3
print("The average of " +str(num1) + " " + str(num2) + " " + str(num3) + " " + "is " + str(round(avg,2)))
Edit:
For checking forcing an input of 3 numbers, and error checking:
def main():
if len(sys.argv) != 4:
print("You did not enter the correct amount of arguments")
else:
try:
num1 = int(sys.argv[1])
num2 = int(sys.argv[2])
num3 = int(sys.argv[3])
avg = (num1 + num2 + num3)/3
print(f"The average of {num1} {num2} {num3} is {round(avg, 2)}")
except (UnboundLocalError, IndexError) as e:
# When you don't pass any args
print("You need to pass arguments")
print(f"($ python avg.py 3 1 2)\n Error = {e}")
except ValueError as e:
# You need to use numbers
print(f"You need to pass arguments as ints")
print(f"(1 or 432. not 1.2, 324.0)\n Error = {e}")
print(f"(1 or 432. not 1.2, 324.0)\n Error = {e}")
See the below for explanation:
len(sys.argv) will be 4 when there are 3 arguments (try print(sys.argv) for exploring this)
You could use a try statement to catch and except two common exceptions when passing args:
def main():
try:
num1 = int(sys.argv[1])
num2 = int(sys.argv[2])
num3 = int(sys.argv[3])
avg = (num1 + num2 + num3)/3
print(f"The average of {num1} {num2} {num3} is {round(avg, 2)}")
except (UnboundLocalError, IndexError) as e:
# When you don't pass any args
print("You need to pass arguments")
print(f"($ python avg.py 3 1 2)\n Error = {e}")
except ValueError as e:
# You need to use numbers
print(f"You need to pass arguments as ints")
print(f"(1 or 432. not 1.2, 324.0)\n Error = {e}")
try will run a block, and except will run when it's listed exceptions are met in the try block (exiting the try loop).
You could also simplify your code to:
nums = [int(x) for x in sys.argv[1:4]]
avg = sum(nums)/3
And access your numbers with
# Same as nums1
nums[0]
and change the length of incoming arguments to anything >= 1 (if you want):
def main():
try:
nums = [int(x) for x in sys.argv[1:len(sys.argv)]]
avg = sum(nums)/len(nums)
print(f"The average of {', '.join([str(x) for x in nums])} is {round(avg, 2)}")
except (UnboundLocalError, IndexError, ZeroDivisionError) as e:
# When you don't pass any args
print("You need to pass arguments")
print(f"($ python avg.py 3 1 2)\n Error = {e}")
except ValueError as e:
# You need to use numbers
print(f"You need to pass arguments as ints")
print(f"(1 or 432. not 1.2, 324.0)\n Error = {e}")
If you are talking about catching the one arg as an error, you could simply catch a value error.
def main():
try:
num1 = int(sys.argv[1])
num2 = int(sys.argv[2])
num3 = int(sys.argv[3])
avg = (num1 + num2 + num3)/3
print("The average of " +str(num1) + " " + str(num2) + " " + str(num3) + " " + "is " + str(round(avg,2)))
except ValueError:
print("All your values need to be ints")
This will ensure that anything outside of a number being passed in as an arg would result in the message All your values need to be ints.
This won't catch any other errors, so you will have to catch them separately. For instance, your first example where you only pass 2 values won't work since there is no num3, but I'm assuming that isn't what you are asking about here.
I'm writing a program where I'm converting a function to prefix and calculate.
from pythonds.basic import Stack
def doMath(op, op1, op2):
if op == "*":
return int(op1) * int(op2)
elif op == "/":
return int(op1) / int(op2)
elif op == "+":
return int(op1) + int(op2)
elif op == "-":
return int(op1) + int(op2)
def postfixEval(postfixExpr):
operandStack = Stack()
tokenList = postfixExpr.split()
for token in tokenList:
print(tokenList)
print("this is token: ", token)
if token in "0123456789":
operandStack.push(token)
print("pop: ",operandStack.peek())
elif not operandStack.isEmpty():
operand2 = operandStack.pop()
operand1 = operandStack.pop()
result = doMath(token, operand1, operand2)
print (result)
operandStack.push(result)
return operandStack.pop()
print(postfixEval('7 8 + 3 2 + /'))
print(postfixEval("17 10 + 3 * 9 /"))
So when I run the first postfixEval it return 3.0,
but at the second print it returns IndexError: pop from empty list
Apparently it's bc of the 2 digit numbers, how could I fix that?
Thanks
When you try:
if token in "0123456789":
operandStack.push(token)
for token = 17, this shall fail since 17 is not in 0123456789.
So change it to this:
try:
if float(token):
operandStack.push(token)
except:
#your code here
HOW THIS WORKS:
When a type of str containing digits and numbers are passed, float() tries to convert it into float. This is only possible only if it is a number.
Replace if token in "0123456789" (checks if token is a substring of "0123456789") with if token.isdigit() (checks if token consists of decimal digits).
This is my code:
import easygui
from random import randint
Minimum = easygui.enterbox(msg = "Choose your minimum number")
Maximum = easygui.enterbox(msg = "Choose your maximum number")
operator = easygui.enterbox( msg="which operator would you like to use? X,/,+ or - ?",title="operator")
questions = easygui.enterbox(msg = "enter your desired amount of questions")
for a in range(int(questions)):
rn1 = randint(int(Minimum), int(Maximum))
rn2 = randint(int(Minimum), int(Maximum))
answer = easygui.enterbox("%s %s %s =?" %(rn1, operator, rn2))
realanswer = operator (int(rn1,rn2))
if answer == realanswer:
print "Correct"
else:
print 'Incorrect, the answer was' ,realanswer
When I try and run it, all the enterboxes come up fine, it is when it looks at line 13 that it produces this error:
int() can't convert non-string with explicit base
I tried running the code without the int(), and then it gives me:
'str' object is not callable
First: Your operator is a string, not a function. You can't call '/'(2,3), so if operator=='/', you still can't call operator(2,3).
Second: int(rn1), int(rn2) is how you convert two different numbers to integers, not int(rn1, rn2).
Third: Return values from randint() are already integers, and don't need to be converted again.
I'd suggest converting your numbers to integers as they're entered, only once, rather than doing so on each reference. Thus:
minimum = int(easygui.enterbox(msg="Choose your minimum number"))
maximum = int(easygui.enterbox(msg="Choose your maximum number"))
operator = easygui.enterbox(msg="which operator would you like to use? X,/,+ or - ?", title="operator")
questions = int(easygui.enterbox(msg="enter your desired amount of questions"))
# Select a function associated with the chosen operator
operators = {
'*': lambda a,b: a*b,
'/': lambda a,b: a/b,
'+': lambda a,b: a+b,
'-': lambda a,b: a-b,
}
operator_fn = operators.get(operator)
if operator_fn is None:
raise Exception('Unknown operator %r' % operator)
for a in range(questions):
rn1 = randint(minimum, maximum))
rn2 = randint(minimum, maximum))
answer = int(easygui.enterbox("%s %s %s = ?" % (rn1, operator, rn2)))
realanswer = operator_fn(rn1,rn2)
if answer == realanswer:
print "Correct"
else:
print 'Incorrect, the answer was', realanswer
Your operator variable hold a string. You have to use that string to determine the real operation to perform.
Something like that:
if operator == "+":
realanswer = rn1 + rn2
elif operator == "-":
realanswer = rn1 - rn2
elif operator == "/":
realanswer = rn1 / rn2
elif operator == "*":
realanswer = rn1 * rn2
else
raise Exception('Bad operator {}'.format(operator))
Or better using the operator module:
# top of your program
import operator
my_operators = { '+': operator.add,
'-': operator.sub,
'*': operator.mul,
'/': operator.div }
# ...
# and later:
realanswer = my_operators[operator](rn1,rn2)
Of course, in a real application, you would somehow have to deal with "invalid" user input. For example using proper exception handling. But this is an other story...
operator is just a string, you still need to write the code that makes it mean something. You could do something like:
if operator in ('+', 'add'):
realanswer = rn1 + rn2
elif operator in ('-', 'subtract'):
realanswer = rn1 - rn2
else:
print operator, "is not valid"
I am working on creating an easygui/python calculator math program and i keep getting this error
Traceback (most recent call last):
File "C:\Python27\Scripts\MathHelper.py", line 83, in <module>
MathType()
TypeError: 'str' object is not callable
I can't figure out why it is happening. I believe it is with the global variable I try to call and change but i can't figure out how to stop the error. I know my code is kind of messy right now i am trying to work a proof of concept.
#MathType == what kind of math to compute. IE. Subtraction or addition
#Selection == Yes or no
math = 1
MathType = "Addition"
loop = 1
import easygui
def start():
print("startMessage")
MathType = easygui.msgbox(msg="Hello and welcome to my Math Helper.",
title = "Welcome")
startMessage = "0"
#End of start
#
#
#
def MathType():
global MathType
print("Math Type Gathered")
MathType = easygui.buttonbox("Select the type of Math you would like to compute:",
title = "Math Selection",
choices = ["Addition", "Subtraction", "Shut Down"] )
#End of MathType
#
#
#
def Addition():
num1 = easygui.enterbox(msg = "Please enter the first Number.",
title = "Addition")
#print(num1)
num2 = easygui.enterbox(msg = "Please enter the second number. "+num1+" + ___ = ___",
title = "Addition")
#print(num2)
easygui.msgbox("Here is your equation: "+num1+" + "+num2+" = ___ ",
title = "Equation")
NUM1 = int(num1)
NUM2 = int(num2)
numFinal = (NUM1 + NUM2)
NUM3 = str(numFinal)
easygui.msgbox(msg="Your answer is: "+NUM3+"",
title="Final")
#print(numFinal)
#End of Addition
#
#
def Subtraction():
num1 = easygui.enterbox(msg = "Please enter the first Number.",
title = "Subtraction")
#print(num1)
num2 = easygui.enterbox(msg = "Please enter the second number. "+num1+" - ___ = ___",
title = "Subtraction")
#print(num2)
easygui.msgbox("Here is your equation: "+num1+" - "+num2+" = ___ ",
title = "Equation")
NUM1 = int(num1)
NUM2 = int(num2)
numFinal = (NUM1 - NUM2)
NUM3 = numFinal
easygui.msgbox(msg="Your answer is: "+NUM3+"",
title="Final")
#print(numFinal)
#End of Subtraction
#
#
def MathFinder():
if MathType == "Addition":
print("Addition")
Addition()
elif MathType == "Subtraction":
print("Subtraction")
Subtraction()
elif MathType == "Shut Down":
exit()
start()
while loop == 1:
MathType()
MathFinder()
At line 4 you have MathType = "Addition"
At line 18 you have def MathType():
The error tells you that it can't call a string.
MathType() is actually MathType = "Addition" which is a string and not a function.
Please try to prevent using the same name for your functions, variables etc.
You have two types of 'MathType', one is a string and other is a function.
You have a function and a string variable named MathType.
There was no problem until I tried to make an input go through validity check and if invalid ask again for input
i'm counting on you for ideas thanks in advance :)
a=0
def reinp(a,b):
while True:
if a in [1,2,3,4,5,6]: #checking for valid input
return int(a)
break
a=input(b)
else:
return print("error")
tried, not working either
def reinp(a,b):
for c in [1,2,3,4,5,6]:
if int(c)==int(a):
return int(a)
break
else:
a=input(b)
a=reinp(a,'Test: ')
This one is the first to make a problem
def reinp2(a,b): #trying to check if it's a number and can be turned to float if not ask again
while check(a):
a=input(b)
return float(a)
def check(a):
try:
float(a)
return False
except ValueError:
return True
Right now the problem is after the check it never breaks free from any while loop
i tried in place of while True:if...break,
while correct:
if... correct=False
didn't work
and it just asks again and again even a condition is met...
there is no raw_input in python 3.2 so i can't use that either
reinp2() is there so if there a solution found for reinp() the same could apply for reinp2() as well a and b are just variables ans[n]=reinp2(ans[n],"Input n: ") the same with reinp() just for another type of variable (one that can be float as well)
The code as it is now show no syntax errors
P.S. i'm using Python 3.2
[EDIT: Deleted original answer, since no longer relevant with fixed formatting on question]
The problem with reinp is that a will be a string, and you're checking it against integers.
...so change:
if a in [1,2,3,4,5,6]: #checking for valid input
to:
if a in ['1','2','3','4','5','6']: #checking for valid input
If you still have a problem with reinp2, perhaps you can show some code that demonstrates the issue. It looks fine to me.
P.S. It's complete i just wanted all of you who helped to know it's running without is any glitches i even customized it so it could receive initial data :) if someone need a permutation solver you know where to find it :)
If someone wants the script:
from math import *
ans=['n','k','choice',0,0,0,0,0]
n,k=0,1
a=['''1 For Permutations P (from n) = n
2 For Variations V (k emelments from n-th class) = n!/(n-k)!
3 For Combinations C (k emelments from n-th class) = n!/(k!(n-k)!) = ( n )
4 Use last answer. ( k )
5 Second Memory
6 Clear memory
Your choice is : ''',
'''+ to add
- to substract
* to multiply
/ to divide
You will undertake?: ''',
"The answer is: "]
def perm():
global ans
ans[n]=reinp2(ans[n],"Input n: ")
if ans[5]==0:
ans[3]=factorial(ans[n])
ans[6]=ans[3]
return print(a[2], ans[6])
else:
ans[4]=factorial(ans[n])
ans[6]=ops(ans[3],ans[4],ans[5])
return print(a[2], ans[6])
ans[n]=''
ans[k]=''
def var():
global ans
ans[n]=reinp2(ans[n],"Input n: ")
ans[k]=reinp2(ans[k],"Input k: ")
if ans[5]==0:
ans[3]=factorial(ans[n])/(factorial(ans[n]-ans[k]))
ans[6]=ans[3]
return print(a[2], ans[6])
else:
ans[4]=factorial(ans[n])/(factorial(ans[n]-ans[k]))
ans[6]=ops(ans[3],ans[4],ans[5])
return print(a[2], ans[6])
ans[n]=''
ans[k]=''
def comb():
global ans
ans[n]=reinp2(ans[n],"Input n: ")
ans[k]=reinp2(ans[k],"Input k: ")
if ans[5]==0:
ans[3]=factorial(ans[n])/((factorial(ans[n]-ans[k]))*(factorial(ans[k])))
ans[6]=ans[3]
return print(a[2], ans[6])
else:
ans[4]=factorial(ans[n])/((factorial(ans[n]-ans[k]))*(factorial(ans[k])))
ans[6]=ops(ans[3],ans[4],ans[5])
return print(a[2], ans[6])
ans[n]=''
ans[k]=''
def ent():
global ans,a
ans[2]=reinp(ans[2],a[0])
if ans[2]==5:
if ans[3]!=0:
ans[7]=ans[3]
print(ans[7])
ent()
if ans[2]==6:
clear()
print("Done!")
ent()
if ans[3]==0 and ans[2]==4:
print('The memory is empty...')
ent()
elif ans[3]!=0 and ans[2]==4:
ans[3]=ans[3]
ans[5]=reinp1(ans[5],a[1])
if ans[5] == '+' :
ans[5]='add'
print("Adding")
elif ans[5] == '-' :
ans[5]='sub'
print("Substracting")
elif ans[5] == '*' :
ans[5]='mul'
print("Multiplication")
elif ans[5] == '/' :
ans[5]='div'
print("Dividing")
ans[2]='choice'
ent()
if ans[2]==1:
perm()
elif ans[2]==2:
var()
elif ans[2]==3:
comb()
clear1()
ent()
def ops(a,b,c):
if c=='add':
return a+b
if c=='sub':
return a-b
if c=='mul':
return a*b
if c=='div':
return a/b
def reinp(a,b):
while True:
a=input(b)
if str(a) in ['1','2','3','4','5','6']:
return int(a)
break
else:
print('There was an error please try again:')
def reinp1(a,b):
while True:
a=input(b)
if a in ["+", "-", "*", "/"]:
return a
break
def reinp2(a,b):
while check2(a):
a=input(b)
return float(a)
def check2(a):
try:
float(a)
return False
except ValueError:
return True
def clear():
ans[0]='n'
ans[1]='k'
ans[2]='choice'
ans[3]=0
ans[4]=0
ans[5]=0
ans[7]=ans[6]
ans[6]=0
def clear1():
ans[0]='n'
ans[1]='k'
ans[2]='choice'
ent()