I made this basic Python calculator. It just does addition, subtraction, division, and multlipication.
I feel like the code is a mess, but it does what I want it to, and I feel like it does it effectively.
import operator
def calculate (first_number, operation_type, second_number):
if operation_type == 'a':
answer = first_number + second_number
answer_text = f"{first_number} + {second_number} = {answer}"
if operation_type == 's':
answer = first_number - second_number
answer_text = f"{first_number} - {second_number} = {answer}"
if operation_type == 'm':
answer = first_number * second_number
answer_text = f"{first_number} x {second_number} = {answer}"
if operation_type == 'd':
answer = first_number / second_number
answer_text = f"{first_number} \xF7 {second_number} = {answer}"
return answer_text
while True:
while True:
try:
first_number = int(input("Enter first number: "))
break
except ValueError:
print ("Enter a number!\n")
pass
while True:
operation_type = str(input("\nA - add\nS - subtract\nM - multiply\nD - divide\nEnter operation type: "))
operation_type = operation_type.lower()
if operation_type in {'a', 'm', 'd', 's'}:
break
else:
print ("Invalid operation type!\n")
pass
while True:
try:
second_number = int(input("\nEnter second number: "))
break
except ValueError:
print ("Enter a number!\n")
pass
print (calculate (first_number, operation_type, second_number))
run_again = str(input("Run again? Type 'y' to continue, or q to quit: "))
if run_again.lower() == 'y':
pass
if run_again.lower() == 'q':
break
elif run_again.lower() != 'y' and run_again.lower() != 'q':
print ("Invalid entry")
break
1 Answer 1
You imported operator, but did not take advantage of it. That's
unfortunate, because the module contains exactly what a simple calculator
program needs: binary functions for arithmetic. Your calculate()
function
could reduce to this:
import operator
OPERATIONS = {
'a': operator.add,
's': operator.sub,
'm': operator.mul,
'd': operator.truediv,
}
def calculate(a, op, b):
return OPERATIONS[op](a, b)
If code is repetitive, functions usually help. Most of your code is
repetitive stuff to get user input. When you see that kind of repetition, your
first instinct should be to extract out the common parts into a function.
Collecting user input usually involves three things: (1) a prompt telling the
user what to enter, (2) code to convert the input string into the desired type
of value, and (3) code to validate that value. The "code" to convert and
validate can often take the form of built-in functions/methods (for example,
int
, float
, or str.lower
) or, when needed, short functions or lambdas
that you define. Here's one way to implement a user-input function in a fairly
generalized way applicable to many programs:
def get_input(prompt, convert, validate):
invalid_msg = 'Invalid input.'
while True:
reply = input(prompt + ': ')
try:
val = convert(reply)
if validate(val):
return val
else:
print(invalid_msg)
except Exception as e:
print(invalid_msg)
Put all code in functions. Even in small programs. Your calculator code becomes fairly simple once you have a user-input function to handle the grubby details.
def main():
op_prompt = '\nA - add\nS - subtract\nM - multiply\nD - divide\nEnter operation'
op_is_valid = lambda x: x in OPERATIONS
yn_is_valid = lambda x: x in 'yn'
always_valid = lambda x: True
while True:
a = get_input('Enter first number', int, always_valid)
op = get_input(op_prompt, str.lower, op_is_valid)
b = get_input('Enter second number', int, always_valid)
result = calculate(a, op, b)
print(result)
if get_input('Run again [y/n]', str.lower, yn_is_valid) == 'n':
break
if __name__ == '__main__':
main()
Next steps: better user experience. (1) This code above does not handle the division-by-zero scenario, but you could easily make that adjustment. (2) Support floats: no good reason not to. (3) Consider simplifying the burden on the user: instead of forcing them to engage in four discrete dialogues with the computer (first number? operator? second number? continue?), which becomes tedious very rapidly, just let them type a normal arithmetic expression (delimited by spaces) and interpret a blank entry as the signal for quit. Here's what a session might look like.
Simple calculator:
12 + 13
=> 25
5 - 3
=> 2
3 / 0
=> Error: division by zero
9 * 9
=> 81
Goodbye.