I am toying around and playing a lot with defining a function. I'm trying to get extremely comfortable with it. The code I have wrote works fairly well, but definitely is not perfect. Also, the function I made called playagain
is having some errors. When I type in "Yes" for the input I'm getting a strange TypeError. If you can fix that, please explain to me how, in the simplest way possible.
import sys
OPTIONS = ["Divide", "divide", "Multiply", "multiply", "Add", "add", "Subtract", "subtract"]
def userinput():
while True:
try:
number = int(input("Number: "))
break
except ValueError:
print("NOPE...")
return number
def operation():
while True:
operation = input("Multiply/Divide/Add: ")
if operation in OPTIONS:
break
else:
print("Not an option.")
return operation
def playagain():
while True:
again = input("Again? Yes/No: ")
if again == "Yes" or again == "yes":
break
elif again == "No" or again == "no":
sys.exit(0)
else:
print("Nope..")
def multiply(x,y):
z = x * y
print(z)
def divide(x,y):
z = x / y
print(z)
def add(x,y):
z = x + y
print(z)
def subtract(x,y):
z = x - y
print(z)
while True:
operation = operation()
x = userinput()
y = userinput()
if operation == "add" or operation == "Add":
add(x,y)
elif operation == "divide" or operation == "Divide":
divide(x,y)
elif operation == "multiply" or operation == "Multiply":
multiply(x,y)
elif operation == "subtract" or operation == "Subtract":
subtract(x,y)
playagain()
I tried defining as much functions as possible to make it simpler and easier to fix and debug. Please let me know what you think.
NOTE: I am not making this program to actually be a beneficial program. I am simply using it to help myself with the defining a function portion of Python.
-
\$\begingroup\$ possible duplicate of Python Calculator \$\endgroup\$200_success– 200_success2013年09月15日 08:13:27 +00:00Commented Sep 15, 2013 at 8:13
-
\$\begingroup\$ @200_success It's not a duplicate, but a follow-up question. The code is not the same, but an already much improved version of the code in the previous question. \$\endgroup\$tobias_k– tobias_k2013年09月15日 08:42:38 +00:00Commented Sep 15, 2013 at 8:42
-
1\$\begingroup\$ @tobias_k I recognize and applaud the improvements, but it's still fundamentally the same question, and any answers to this question will be very similar to those of the predecessor. There are also plenty of suggestions in previous answers that have not been incorporated yet. \$\endgroup\$200_success– 200_success2013年09月15日 08:49:47 +00:00Commented Sep 15, 2013 at 8:49
3 Answers 3
Of the feedback on your earlier version of this programme, the most obvious thing that you haven't done yet is to use lower()
on text inputs so that you only have to compare against lower case options. e.g.
again = input("Again? Yes/No: ").lower()
if again == "yes":
break
elif again == "no":
sys.exit(0)
It might be useful to know that the operations you define already exist as methods of numeric variables in Python, called __mul__
, __add__
, etc., and are also available within the operator
module. e.g. operator.add(3, 4)
is equivalent to 3 + 4
. So you could, for example, do this
import operator
OPTIONS = {
'divide': operator.truediv,
'multiply': operator.mul,
'add': operator.add,
'subtract': operator.sub
}
def user_input():
while True:
try:
return int(input("Number: "))
except ValueError:
print("NOPE...")
def get_operation():
while True:
operation = input("Multiply/Divide/Add/Subtract: ").lower()
try:
return OPTIONS[operation]
except KeyError:
print("Not an option.")
def play_again():
while True:
again = input("Again? Yes/No: ").lower()
if again == "yes":
return True
elif again == "no":
return False
else:
print("Nope..")
while True:
operation = get_operation()
x = user_input()
y = user_input()
print(operation(x, y))
if not play_again():
break
-
\$\begingroup\$ Your code didn't work for me, but it's still a very nice answer. I have provided corrections in a separate answer. \$\endgroup\$Vedran Šego– Vedran Šego2013年09月15日 11:15:03 +00:00Commented Sep 15, 2013 at 11:15
-
\$\begingroup\$ Thanks, I was mixing up Python 2 and 3. I corrected it above to Python 3 as that is what the question uses. \$\endgroup\$Stuart– Stuart2013年09月15日 11:31:54 +00:00Commented Sep 15, 2013 at 11:31
-
\$\begingroup\$ Thanks @Stuart I appreciate your answer! I will definitely start using the .lower() , I never really knew about it or knew what it did. I will study your code and make some changes. \$\endgroup\$TheSuds13– TheSuds132013年09月15日 18:10:28 +00:00Commented Sep 15, 2013 at 18:10
Stuart's code is very nicely written, and provides much to a learner, but it didn't work for me. Fixed versions are too long for just a comment, so here they are.
Python 2
The exact version I use: 2.7.3
import operator
OPTIONS = {
'divide': operator.div,
'multiply': operator.mul,
'add': operator.add,
'subtract': operator.sub
}
def user_input():
while True:
try:
return input("Number: ")
except ValueError:
print("NOPE...")
def get_operation():
while True:
operation = raw_input("Multiply/Divide/Add/Subtract: ").lower()
try:
return OPTIONS[operation]
except KeyError:
print("Not an option.")
def play_again():
while True:
again = raw_input("Again? Yes/No: ").lower()
if again == "yes":
return True
elif again == "no":
return False
else:
print("Nope..")
while True:
operation = get_operation()
x = user_input()
y = user_input()
print operation(x, y)
if not play_again():
break
In Python 2, input
returns an integer, so int(input(...))
is redundant, and inputting string (for operation and going again) fails. The later is fixed by using raw_input
.
Python 3
The exact version I use: 3.2.3
import operator
OPTIONS = {
'divide': operator.truediv,
'multiply': operator.mul,
'add': operator.add,
'subtract': operator.sub
}
def user_input():
while True:
try:
return int(input("Number: "))
except ValueError:
print("NOPE...")
def get_operation():
while True:
operation = input("Multiply/Divide/Add/Subtract: ").lower()
try:
return OPTIONS[operation]
except KeyError:
print("Not an option.")
def play_again():
while True:
again = input("Again? Yes/No: ").lower()
if again == "yes":
return True
elif again == "no":
return False
else:
print("Nope..")
while True:
operation = get_operation()
x = user_input()
y = user_input()
print(operation(x, y))
if not play_again():
break
The obvious error here was the last print
statement: it's a function in Python 3, so print operation(x, y)
had to be replaced with print(operation(x, y))
.
The less obvious one is operator.div
which doesn't exist in Python 3, but was instead replaced by operator.truediv
and operator.floordiv
. In the spirit of this program, I assumed that the former is what was intended.
[Warning, Ugly Code Ahead...]
I do not quite understand the question, however, I am assuming that you would like to build a calculator application. I have quickly "whipped up" this code. It is compatible with python3, and comes with a graphical user interphase.
Instead of creating that huge function to determine the operator, just use the eval()
function instead in a GUI.
As seen in the function Calculate()
, I am actually getting the text input from the display screen and just evaluating it. I also error check using a try
and except
statement.
Calculator with a GUI:
from tkinter import *
from tkinter import ttk
import time
import random
tk = Tk()
canvas = Canvas(tk, height=400, width=300, bg = 'white')
canvas.pack()
tk.title('Calculator')
tk.resizable(False, False)
class Calculator:
def Title(self):
title = Label(tk, text = 'Calculator', font='Times, 20')
title.place(x = 0, y = 10)
def EntryBar(self):
self.CalculationBox = Text(tk, height=2, width=27, font='Times, 15', bg = 'gray60')
self.CalculationBox.place(x = 0, y = 60)
self.counter = 1
def DisplayCal(self, num):
self.CalculationBox.insert(END, num)
def Calculate(self):
try:
answer = eval(self.CalculationBox.get('1.0', END))
self.CalculationBox.delete("1.0", END)
#print(answer) #For debugging
self.CalculationBox.insert(END, answer)
except Exception:
self.CalculationBox.delete("1.0", END)
self.CalculationBox.insert(END, "Error")
c = Calculator()
class Buttons:
def Buttons(self):
self.ZeroBtn = Button(tk, text = '0', height=2, width=8, bg = 'gray60', fg = 'white', command = lambda: c.DisplayCal(num=0))
self.ZeroBtn.place(x = 120, y = 360)
self.OneBtn = Button(tk, text = '1', height=2, width=8, bg = 'gray60', fg = 'white', command = lambda: c.DisplayCal(num=1))
self.OneBtn.place(x = 53, y = 320)
self.TwoBtn = Button(tk, text = '2', height=2, width=8, bg = 'gray60', fg = 'white', command = lambda: c.DisplayCal(num=2))
self.TwoBtn.place(x = 120, y = 320)
self.ThreeBtn = Button(tk, text = '3', height=2, width=8, bg = 'gray60', fg = 'white', command = lambda: c.DisplayCal(num=3))
self.ThreeBtn.place(x = 187, y = 320)
self.FourBtn = Button(tk, text = '4', height=2, width=8, bg = 'gray60', fg = 'white', command = lambda: c.DisplayCal(num=4))
self.FourBtn.place(x = 53, y = 280)
self.FiveBtn = Button(tk, text = '5', height=2, width=8, bg = 'gray60', fg = 'white', command = lambda: c.DisplayCal(num=5))
self.FiveBtn.place(x = 120, y = 280)
self.SixBtn = Button(tk, text = '6', height=2, width=8, bg = 'gray60', fg = 'white', command = lambda: c.DisplayCal(num=6))
self.SixBtn.place(x = 187, y = 280)
self.SevenBtn = Button(tk, text = '7', height=2, width=8, bg = 'gray60', fg = 'white', command = lambda: c.DisplayCal(num=7))
self.SevenBtn.place(x = 53, y = 240)
self.EightBtn = Button(tk, text = '8', height=2, width=8, bg = 'gray60', fg = 'white', command = lambda: c.DisplayCal(num=8))
self.EightBtn.place(x = 120, y = 240)
self.NineBtn = Button(tk, text = '9', height=2, width=8, bg = 'gray60', fg = 'white', command = lambda: c.DisplayCal(num=9))
self.NineBtn.place(x = 187, y = 240)
self.AddBtn = Button(tk, text = '+', height=2, width=8, bg = 'gray60', fg = 'white', command = lambda: c.DisplayCal(num='+'))
self.AddBtn.place(x = 53, y = 200)
self.MultBtn = Button(tk, text = 'x', height=2, width=8, bg = 'gray60', fg = 'white', command = lambda: c.DisplayCal(num='*'))
self.MultBtn.place(x = 120, y = 200)
self.DivBtn = Button(tk, text = '÷', height=2, width=8, bg = 'gray60', fg = 'white', command = lambda: c.DisplayCal(num='/'))
self.DivBtn.place(x = 187, y = 200)
self.SubBtn = Button(tk, text = '-', height=2, width=8, bg = 'gray60', fg = 'white', command = lambda: c.DisplayCal(num='-'))
self.SubBtn.place(x = 53, y = 160)
self.EquBtn = Button(tk, text = '=', height=2, width=8, bg = 'gray60', fg = 'white', command = c.Calculate)
self.EquBtn.place(x = 187, y = 160)
self.ClsBtn = Button(tk, text='Clear', height=2, width=8, bg = 'gray60', fg = 'white', command = lambda: c.CalculationBox.delete('1.0',END))
self.ClsBtn.place(x = 120, y = 160)
b = Buttons()
def main():
c.Title()
c.EntryBar()
b.Buttons()
main()
tk.mainloop()