9
\$\begingroup\$

What do you think about this simple calculator?

while True:
    print('Options:')
    print('Enter \'a\' to add two numbers')
    print('Enter \'s\' to subtract two numbers')
    print('Enter \'m\' to multiply two numbers')
    print('Enter \'d\' to divide two numbers')
    print('Enter \'q\' to quit the program')
    response=str(input(':')).lower()
    if response=='q':
        break
    elif response=='a':
        while True:
           try:
               num1=float(input('Enter a number:'))
               break
           except(TypeError,ValueError):
               print('*(Input Error) Enter valid number*')
               continue
        while True:
            try:
                num2=float(input('Enter another number:'))
                break
            except(TypeError,ValueError):
                print('*(Input Error) Enter valid number*')
                continue
        result=num1+num2
        print('The answer is '+str(result))
        print()
    elif response=='s':
        while True:
            try:
                num1=float(input('Enter a number:'))
                break
            except(TypeError,ValueError):
                print('*(Input Error) Enter valid number*')
                continue
        while True:
            try:
                num2=float(input('Enter another number:'))
                break
            except(TypeError,ValueError):
                print('*(Input Error) Enter valid number*')
                continue
        result=num1-num2
        print('The answer is '+str(result))
        print()
    elif response=='m':
        while True:
            try:
                num1=float(input('Enter a number:'))
                break
            except(TypeError,ValueError):
                print('*(Input Error) Enter valid number*')
                continue
        while True:
            try:
                num2=float(input('Enter another number:'))
                break
            except(TypeError,ValueError):
                print('*(Input Error) Enter valid number*')
                continue
        result=num1*num2
        print('The answer is '+str(result))
        print()
    elif response=='d':
        while True:
            try:
                num1=float(input('Enter a number:'))
                break
            except(TypeError,ValueError):
                print('*(Input Error) Enter valid number*')
                continue
        while True:
            try:
                num2=float(input('Enter another number:'))
                break
            except(TypeError,ValueError):
                print('*(Input Error) Enter valid number*')
                continue
        result=num1/num2
        print('The answer is '+str(result))
        print()
    else:
        print('*Unknown input*')
    continue
\$\endgroup\$

1 Answer 1

12
\$\begingroup\$

Welcome to the world of beginner Python programming, and programming in general! Python is a nice language to learn and start out with!

Allow me to give you some tips and pointers, with the hope that you will be able to learn a little from them.

Also, allow me to apologize in advance for this massive wall of text. I may have gone a little bit overboard in my review and analysis, but I wanted to make sure you would understand my revisions and some of the code I've added, in the event you are unfamiliar with the functionality I implement and use in the reviewed and revised code.


Add white space for readability, and obey PEP8 rules for whitespace around assignment and equality operators

Python is extremely indentation-based. This means an indent usually indicates a code block that needs executed underneath of another one (such as your if statements have, etc).

However, Python also benefits from having white space added at logical locations for readability. I usually define these locations as between loops and other sections of code, between functional statements (addition, subtraction, etc.) and output, between the end of an if statement and the beginning of its elif or else blocks, after the end of an entire if block, etc.

There is also a rule for Python code style, called the PEP8 which dictates whitespace around assignment statements, equality operators (such as ==), and also arithmetic operators (+, -, *, /, and others), stating that a space is necessary around them.

This is your code with the whitespace per my guidelines and the PEP8 guidelines. My further reviews from here will be using this as a base.

while True:
    print('Options:')
    print('Enter \'a\' to add two numbers')
    print('Enter \'s\' to subtract two numbers')
    print('Enter \'m\' to multiply two numbers')
    print('Enter \'d\' to divide two numbers')
    print('Enter \'q\' to quit the program')

    response = str(input(':')).lower()

    if response == 'q':
        break

    elif response == 'a':
        while True:
            try:
                num1 = float(input('Enter a number:'))
                break
            except(TypeError, ValueError):
                print('*(Input Error) Enter valid number*')
                continue

        while True:
            try:
                num2 = float(input('Enter another number:'))
                break
            except(TypeError, ValueError):
                print('*(Input Error) Enter valid number*')
                continue

        result = num1 + num2

        print('The answer is ' + str(result))
        print()

    elif response == 's':
        while True:
            try:
                num1 = float(input('Enter a number:'))
                break
            except(TypeError, ValueError):
                print('*(Input Error) Enter valid number*')
                continue

        while True:
            try:
                num2 = float(input('Enter another number:'))
                break
            except(TypeError, ValueError):
                print('*(Input Error) Enter valid number*')
                continue

        result = num1 - num2

        print('The answer is ' + str(result))
        print()

    elif response == 'm':
        while True:
            try:
                num1 = float(input('Enter a number:'))
                break
            except(TypeError, ValueError):
                print('*(Input Error) Enter valid number*')
                continue

        while True:
            try:
                num2 = float(input('Enter another number:'))
                break
            except(TypeError, ValueError):
                print('*(Input Error) Enter valid number*')
                continue

        result = num1 * num2

        print('The answer is ' + str(result))
        print()

    elif response == 'd':
        while True:
            try:
                num1 = float(input('Enter a number:'))
                break
            except(TypeError, ValueError):
                print('*(Input Error) Enter valid number*')
                continue

        while True:
            try:
                num2 = float(input('Enter another number:'))
                break
            except(TypeError, ValueError):
                print('*(Input Error) Enter valid number*')
                continue

        result = num1 / num2

        print('The answer is ' + str(result))
        print()

    else:
        print('*Unknown input*')

    continue

Move non-quit responses to separate "if" block, so we can do some tasks without repeating code.

One of the major guidelines of programming is that if you are doing something that requires you to copy and paste code in all the time to do the same thing, chances are there's a better implementation.

You currently do this in every single block of code under each conditional check for the response entered, except for quitting and invalid responses:

while True:
    try:
        num1 = float(input('Enter a number:'))
        break
    except(TypeError, ValueError):
        print('*(Input Error) Enter valid number*')
        continue

while True:
    try:
        num2 = float(input('Enter another number:'))
        break
    except(TypeError, ValueError):
        print('*(Input Error) Enter valid number*')
        continue

We can easily move this to outside the if block, if we separate the a, s, m, and d response checks to somewhere else, so we don't have to repeat all the code, which actually will save you a lot of lines of code. This is the new set of if/elif statements, with the 'quit' response checked before we even begin to look at other responses, and the deletion of the "else" clause that you had in there:

if response == 'q':
    break

while True:
    try:
        num1 = float(input('Enter a number:'))
        break
    except(TypeError, ValueError):
        print('*(Input Error) Enter valid number*')
        continue

while True:
    try:
        num2 = float(input('Enter another number:'))
        break
    except(TypeError, ValueError):
        print('*(Input Error) Enter valid number*')
        continue

if response == 'a':
    result = num1 + num2

elif response == 's':
    result = num1 - num2

elif response == 'm':
    result = num1 * num2

elif response == 'd':
    result = num1 / num2

Note that while I drop the "Unknown Input" check (that else statement at the end), we're going to add it back in elsewhere in the code in my next recommendation.


Move "Invalid Input" check to second thing checked in the if/elif block for "Quit" checking

This recommendation builds from the previous recommendation above this one; it should not be implemented without the previous recommendation, as it builds off of the previous recommendation

You'll note that I removed the else block that handled "Unknown Input" captures in my earlier recommendation. That's because we can implement it in a better place, and earlier on in the code, and handle things as a "Check if input is valid before anything else" approach, which is what we'll cover in this section.

Basically, we don't need to put the "Invalid Input" check at the bottom. Instead, we can check it at the beginning!

This is the code that will do that:

if response == 'q':
    break
elif response not in 'asmd':
    print('*Unknown input*')
    continue

Because you're a beginner, let me break down the elif here. Basically this says "Is the value of response contained within this string of valid response characters?", and if it is not, then it will print the "Unknown Input" error, and continue on to the next iteration of the loop - skipping all other code below it.


Unnecessary continue statement at end of loop

In your original code, you have the continue statement at the end of the code underneath the while loop. This is unnecessary - when the end of the code under the loop is reached, it will automatically continue on to the next iteration, and you don't need the continue statement here.

You can just remove that continue statement.


Improper checking of 'length' of response

This builds off my two earlier recommendations for changing your if and elif blocks for "Quit" and "Invalid Response" to their own block at the beginning, and then have a separate if/elif block for response checking only.

So, in my recommendations, I don't properly check the length of the response provided. That means I potentially introduce breakage where it's listed as "unknown input" So, let's do that as part of "Invalid Input" checks, by checking if the length of the response is greater than one, or if it's not in the 'valid responses' we defined. The code below does that.

if response == 'q':
    break
elif len(response) > 1 or response not in 'asmd':
    print('*Unknown input*')
    continue

Make Output and Options Prompt a little cleaner

This is more or less up to each programmer, but I believe that the output and prompts you use are a little... cluttered, and harder to read. I also believe input could be better handled in terms of providing users with the prompt.

Let's start with the options prompt first. We can reorganize and revise these to make output a little nicer, and grab the option in a nicer way than just a colon and a prompt line:

print('Enter \'a\' to add two numbers')
print('Enter \'s\' to subtract two numbers')
print('Enter \'m\' to multiply two numbers')
print('Enter \'d\' to divide two numbers')
print('Enter \'q\' to quit the program')

response = str(input('Select an option: ')).lower()

Note that we got rid of that first print("Options:") item. You can add it back in if you want.

Next, let's work on the prompts for the two numbers being worked with, and the output. I think it would benefit from some line breaks to sort of 'separate up' the content to make it a little more readable.

I'd like to introduce you to an escaped character sequence: \n. In a string, \n is interpreted as a line break, which generates a blank line in the usages I'm putting in place here when actually displayed to the user.

The following lines should be changed accordingly, to make your output a little nicer:

  • num1 = float(input('Enter a number:')) should become num1 = float(input('\nEnter a number: '))
  • num2 = float(input('Enter another number:')) should become num2 = float(input('\nEnter another number: '))
  • print('The answer is ' + str(result)) should become print('\nThe answer is ' + str(result) + '\n')
  • print() should become print('------------------\n').

This results in program output a little like this, then (using a, 1, and 1):

Enter 'a' to add two numbers
Enter 's' to subtract two numbers
Enter 'm' to multiply two numbers
Enter 'd' to divide two numbers
Enter 'q' to quit the program
Select an option: a

Enter a number: 1

Enter another number: 1

The answer is 2.0

------------------

Enter 'a' to add two numbers
Enter 's' to subtract two numbers
Enter 'm' to multiply two numbers
Enter 'd' to divide two numbers
Enter 'q' to quit the program
Select an option: q

Avoid escaping ' characters, by using " around the strings containing them

This was originally pointed out in comments by Dex'ter.

In your print statements where you print out the list of available options for the user, you can avoid having to use \' to escape the 's by using the quotation marks around the entire string instead of apostrophes., like so:

print("Enter 'a' to add two numbers")
print("Enter 's' to subtract two numbers")
print("Enter 'm' to multiply two numbers")
print("Enter 'd' to divide two numbers")
print("Enter 'q' to quit the program")


Complete Code, After Recommendations

This is the code, after all my recommendations from above implemented, in its entirety:

while True:
    print("Enter 'a' to add two numbers")
    print("Enter 's' to subtract two numbers")
    print("Enter 'm' to multiply two numbers")
    print("Enter 'd' to divide two numbers")
    print("Enter 'q' to quit the program")

    response = str(input('Select an option: ')).lower()

    if response == 'q':
        break
    elif len(response) > 1 or response not in 'asmd':
        print('*Unknown input*\n')
        continue

    while True:
        try:
            num1 = float(input('\nEnter a number: '))
            break
        except(TypeError, ValueError):
            print('*(Input Error) Enter valid number*')
            continue

    while True:
        try:
            num2 = float(input('\nEnter another number: '))
            break
        except(TypeError, ValueError):
            print('*(Input Error) Enter valid number*')
            continue

    if response == 'a':
        result = num1 + num2

    elif response == 's':
        result = num1 - num2

    elif response == 'm':
        result = num1 * num2

    elif response == 'd':
        result = num1 / num2

    print('\nThe answer is ' + str(result) + '\n')
    print('------------------\n')
\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.