3
\$\begingroup\$

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
ggorlen
4,1572 gold badges19 silver badges28 bronze badges
asked Apr 19, 2022 at 2:21
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

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.
answered Apr 19, 2022 at 15:35
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.