4
\$\begingroup\$

This is my first big project that I've made in Python. I've noticed as I was writing it that it's extremely repetitive and I just don't know how to make it less so.

# This is a basic calculator that also has area/volume calculations for certain shapes.

import math
import sys

# Main menu
def main():
    choice = input('Which operation would you like?\n'
                   '1) Area\n'
                   '2) Volume\n'
                   '3) Basic Math\n'
                   '4) Quit\n')

    if choice == '1':
        area()
    elif choice == '2':
        volume()
    elif choice == '3':
        basic_math()
    elif choice == '4':
        sys.exit('Choice 4 selected.  Quitting...')
    else:
        print('I didn\'t understand your input!')


# Menu to choose which area you'd like to calculate
def area():
    choice = input('Please enter what you\'d like to calculate\n'
                   '1) Area of a square\n'
                   '2) Area of a rectangle\n'
                   '3) Area of a circle\n'
                   '4) Area of a triangle\n'
                   '5) Area of a equilateral triangle\n'
                   '6) Area of a trapezoid\n'
                   '7) Area of a cube\n'
                   '8) Quit\n'
                   '9) Main Menu\n')

    try:
        if choice == '1':
            area_of_square()

        elif choice == '2':
            area_of_rectangle()

        elif choice == '3':
            area_of_circle()

        elif choice == '4':
            area_of_triangle()

        elif choice == '5':
            area_of_equilateral_triangle()

        elif choice == '6':
            area_of_trapezoid()

        elif choice == '7':
            area_of_cube()

        elif choice == '8':
            sys.exit('Choice 8 selected.  Quitting...')

        elif choice == '9':
            main()

        else:
            print('I didn\'t understand your input!')
            main()
    except NameError:
        print('You forgot to define a function!')
        area()

# Volume main menu
def volume():
    choice = input('Please enter what you\'d like to calculate\n'
                   '1) Volume of a cube\n'
                   '2) Volume of a sphere\n'
                   '3) Volume of a cylinder\n'
                   '4) Volume of a cone\n'
                   '5) Volume of a rectangular prism\n'
                   '6) Volume of a triangular prism\n'
                   '7) Quit\n'
                   '8) Main menu\n')
    try:
        if choice == '1':
            volume_of_cube()

        elif choice == '2':
            volume_of_sphere()

        elif choice == '3':
            volume_of_cylinder()

        elif choice == '4':
            volume_of_cone()

        elif choice == '5':
            volume_of_rect_prism()

        elif choice == '6':
            volume_of_tri_prism()

        elif choice == '7':
            sys.exit('Option 7 selected.  Quitting...')

        elif choice == '8':
            main()

        else:
            print('I didn\'t understand your input!')
            volume()

    except NameError:
        print('Programmer forgot to define a function!')
        volume()

# Menu for basic math
def basic_math():
    choice = input('Please enter which operation you would like\n'
                   '1) Addition\n'
                   '2) Subtraction\n'
                   '3) Multiplication\n'
                   '4) Division\n'
                   '5) Quit\n'
                   '6) Menu\n')

    try:
        if choice == '1':
            addition()

        elif choice == '2':
            subtraction()

        elif choice == '3':
            multiplication()

        elif choice == '4':
            division()

        elif choice == '5':
            sys.exit('Option 5 selected.  Quitting...')

        elif choice == '6':
            main()

        else:
            print('I\'m sorry, I didn\'t understand your input.')
            basic_math()
    except NameError:
        print('Programmer forgot to define a function! How lazy of him/her')
        basic_math()

#############################################
# Start Basic Math functions
#############################################

def addition():
    try:
        x = int(input('Please enter your first value '))
        y = int(input('Please enter the next value '))
        print('The sum is {0}'.format(x + y))
    except ValueError:
        print('You entered alphabetic characters!  Please enter integers only.')
        addition()

def subtraction():
    try:
        x = int(input('Please enter your first value '))
        y = int(input('Please enter your next value '))
        print('The value is {0}'.format(x - y))
    except ValueError:
        print('You entered alphabetic characters!  Please enter integers only.')
        subtraction()

def multiplication():
    try:
        x = int(input('Please enter your first value '))
        y = int(input('Please enter your next value '))
        print('The value is {0}'.format(x * y))
    except ValueError:
        print('You entered alphabetic characters!  Please enter integers only.')
        multiplication()

def division():
    try:
        x = int(input('Please enter your first value '))
        y = int(input('Please enter your next value '))
        print('The value is {0}'.format(x / y))
    except ValueError:
        print('You entered alphabetic characters!  Please enter integers only.')
        division()


#################################################
# End Basic Math Functions, start area
#################################################


def area_of_square():
    try:
        area = int(input('The area of your square is... '))
        print(area**2)
    except ValueError:
        print('You entered alphabetic characters!  Please enter integers only.')
        area_of_square()


def area_of_circle():
    try:
        radius = int(input('The area of your circle is... '))
        area = math.pi * radius**2
        print(area)
    except ValueError:
        print('You entered alphabetic characters!  Please enter integers only.')
        area_of_circle()


def area_of_triangle():
    try:
        base = int(input('Please enter the base... '))
        height = int(input('Please enter the height...'))
        print(base * height / 2)
    except ValueError:
        print('You entered alphabetic characters!  Please enter integers only.')
        area_of_triangle()


def area_of_equilateral_triangle():
    try:
        area = int(input('The area of your equilateral triangle is... '))
        x = math.sqrt(3) / 4 * area**2
        print(x)
    except ValueError:
        print('You entered alphabetic characters!  Please enter integers only.')
        area_of_equilateral_triangle()


def area_of_trapezoid():
    try:
        a = int(input('Enter base 1: '))
        b = int(input('Enter base 2: '))
        height = int(input('Enter the height: '))
        # For some reason, when this was on the same line, it messed up the
        # order of operations, so I set the formula into 3 different variables.
        area = a + b
        area1 = area / 2
        area2 = area1 * height
        print('The area is {0}'.format(area2))
    except ValueError:
        print('You entered alphabetic characters!  Please enter integers only.')
        area_of_trapezoid()


def area_of_cube():
    try:
        a = int(input('Enter an edge of your cube... '))
        area = 6 * a**2
        print('The area of your cube is {0}'.format(area))
    except ValueError:
        print('You entered alphabetic characters!  Please enter integers only.')
        area_of_cube()

#######################################################################
# End Area functions here: Start Volume functions.
#######################################################################

def volume_of_cube():
    try:
        a = int(input('Enter an edge of your cube... '))
        volume = a**3
        print('The volume of your cube is {0}'.format(volume))
    except ValueError:
        print('You entered alphabetic characters!  Please enter integers only.')
        volume_of_cube()

def volume_of_cone():
    try:
        r = int(input('Enter the radius... '))
        h = int(input('Enter the height... '))
        volume = math.pi * r**2 * h / 3
        print('The volume of the cone is {0}'.format(volume))
    except ValueError:
        print('You entered alphabetic characters!  Please enter integers only.')
        volume_of_cone()


def volume_of_sphere():
    try:
        r = int(input('Enter the radius of your sphere... '))
        volume = 4/3 * math.pi * r**3
        print('The volume of your sphere is {0}'.format(volume))
    except ValueError:
        print('You entered alphabetic characters!  Please enter integers only.')
        volume_of_sphere()

def volume_of_cylinder():
    try:
        r = int(input('Enter the radius of your cylinder... '))
        h = int(input('Enter the height of your cylinder... '))
        volume = math.pi * r**2 * h
        print('The volume of yoru cylinder is {0}'.format(volume))
    except ValueError:
        print('You entered alphabetic characters!  Please enter integers only.')
        volume_of_cylinder()

def volume_of_rect_prism():
    try:
        w = int(input('Enter the width '))
        h = int(input('Enter the height '))
        l = int(input('Enter the length '))
        volume = l * w * h
        print('The volume of the rectangular prism is {0}'.format(volume))
    except ValueError:
        print('You entered alphabetic characters!  Please enter integers only.')
        volume_of_rect_prism()

#def volume_of_tri_prism():
#    try:
#        a = int(input('Enter 1st base side '))
#        b = int(input('Enter 2nd base side '))
#        c = int(input('Enter 3rd base side '))
#        h = int(input('Enter the height '))
#        volume = 1 / 4 * h
#        volume1 = a**4 + 2(a + b)**2
#        print('The volume of the triangular prism is {0}'.format(volume))
#    except ValueError:
#        print('You entered alphabetic characters!  Please enter integers only.')
#        volume_of_tri_prism()


if __name__ == "__main__":
    main()
\$\endgroup\$

1 Answer 1

4
\$\begingroup\$

The main problem is the repetetiveness and nestedness when it comes to reading user inputs and mapping them to the function calls. You are currently using multiple if/else branches, but, what if you would use a dictionary to map choices into function names:

COMMANDS = {
    '1': addition,
    '2': subtraction,
    '3': multiplication,
    '4': division,
    '5': exit,
    '6': main
}

if choice not in COMMANDS:
    print('I\'m sorry, I didn\'t understand your input.')
    basic_math()
else:
    COMMANDS[choice]()

Note that exit here is a function you might have to exit the app.

Also, look through the third-party apps in the CLI space - there might be a tool that can ease creating this kind of question-choice style programs.


Here are some other notes:

  • the program is too long - split it into multiple logical parts to have a better separation of concern and modularity. For example, the calculations of areas and volumes should be separated from the question-choice handling functions
  • you can use multi-line strings instead of having regular strings with newline characters
  • you can wrap the string inside the print() statement around double quotes so that you won't need to escape the single quote (credit to @Dex'ter):

    "I'm sorry, I didn't understand your input."
    
\$\endgroup\$
8
  • 1
    \$\begingroup\$ You can wrap the string inside the print() statement around double quotes so that you won't need to escape the single quote: print("I'm sorry, I didn't understand your input.") \$\endgroup\$ Feb 13, 2017 at 16:45
  • \$\begingroup\$ I ran this code with your dictionary, but then it runs each function, instead of just stopping at one. Any way around this? \$\endgroup\$ Feb 13, 2017 at 16:46
  • \$\begingroup\$ @LeviPorter you are probably running/calling the functions - make sure to not have () after the function names in the dictionary. \$\endgroup\$
    – alecxe
    Feb 13, 2017 at 16:48
  • \$\begingroup\$ @Dex'ter included your suggestion into the answer, thanks! \$\endgroup\$
    – alecxe
    Feb 13, 2017 at 16:48
  • \$\begingroup\$ @alecxe You were right, I was calling the functions. Thank you. \$\endgroup\$ Feb 13, 2017 at 16:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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