How would I make this more compact and faster? New learner

Sorry to ask a very long question but I am very new to Python. I started a free course on FutureLearn and a task was to create a calculator. The code I had ended up being a lot longer than other answers and it was too big to fit into the comment section. Just looking for tips for any part of my code that could be squished down. First question on StackOverflow so I'm sorry if this is a bad question.

def main():
    operations = ['multiplication', 'division', 'addition', 'subtraction', 'x^y']

    def find_op():
        while True:
            try:
                operation = input('What do you want to do? Addition, subtraction, multiplication, division, or x^y??\n')
                operations.index(operation.lower())
                break
            except ValueError:
                input('Error!, you must input one of the five options, enter to try again.')
        return operations.index(operation.lower())

    operation_index = find_op()

    match operation_index:
        case 0:
            num_question_ending = 'multiply with'
        case 1:
            num_question_ending = 'divide with'
        case 2:
            num_question_ending = 'add with'
        case 3:
            num_question_ending = 'subtract with'
        case 4:
            num_question_ending = 'create an exponential with'

    def add():
        add_ans = global_number1 + global_number2
        print(f'{global_number1} + {global_number2} =\n{add_ans}')

    def sub():
        sub_ans = global_number1 - global_number2
        print(f'{global_number1} - {global_number2} =\n{sub_ans}')

    def mult():
        mult_ans = global_number1 * global_number2
        print(f'{global_number1} multiplied by {global_number2} =\n{mult_ans}')

    def div():
        while True:
            try:
                div_ans = global_number1 / global_number2
                break
            except ZeroDivisionError:
                input('Naughty naughty boy trying to divide by 0. '
                      'Now you gonna have to restart the code. Press enter plz')
                main()
        print(f'{global_number1} divided by {global_number2} =\n{div_ans}')

    def power():
        if global_number1 == 0 and global_number2 == 0:
            input('Naughty boy trying 0^0, dat is undefined boi. Enter to restart the whole thing.')
            main()
        pow_ans = global_number1 ** global_number2
        print(f'{global_number1} to the power of {global_number2} =\n{pow_ans}')

    def get_number1():
        while True:
            try:
                numba1 = input(f'what\'s the first number you want to {num_question_ending}??\n')
                float(numba1)
                break
            except ValueError:
                input('input must be a number. enter to try again.')

        numba1 = float(numba1)
        return numba1

    def get_number2():
        while True:
            try:
                numba2 = input(f'what\'s the second number you want to {num_question_ending}??\n')
                float(numba2)
                break
            except ValueError:
                input('input must be a number. enter to try again.')

        numba2 = float(numba2)
        return numba2

    global_number1 = get_number1()

    global_number2 = get_number2()

    match operation_index:
        case 0:
            mult()
        case 1:
            div()
        case 2:
            add()
        case 3:
            sub()
        case 4:
            power()

    def repeat():
        go_again_ans = input('would you like to go again? Y/N\n')
        if go_again_ans == 'Y':
            main()
        elif go_again_ans == 'N':
            exit()
        else:
            input('Error! You need to answer with either Y or N, enter to try again.')
            repeat()
    repeat()

if __name__ == '__main__':
    main()

1 answer

  • answered 2021-11-29 02:37 Ahmed Salim

    I think this is the most concise way I used the menu prompt to save the text, first class functions to not search for the operation and a lambda functions to avoid defining each function in 3 lines, also not checking for the zero I only catch the exception

    I am also still learning so excuse me if something is off

    Thanks

    menu_prompt = f"""
    Please enter:
    'a' For addition
    's' For Subtraction
    'm' For Multiplication
    'd' For Division
    'p' For Exponential operations
    'q' To quit
    """
    
    add = lambda x, y: f"{x} + {y} = { x + y}"
    subtract = lambda x, y: f"{x} - {y} = { x - y}"
    multiply = lambda x, y: f"{x} * {y} = { x * y}"
    divide = lambda x, y: f"{x} / {y} = { x / y:.2f}"
    power = lambda x, y: f"{x} ^ {y} = { x ** y}"
    
    operations = {
        'a': add,
        's': subtract,
        'm': multiply,
        'd': divide,
        'p': power
    }
    
    def get_number(order):
        while True:
            try:
                return float(input(f"Please enter the {order} number: "))
                
            except ValueError:
                print("Please enter a valid number")
    
    def run_selected_operation(operation):
        x = get_number("first")
        y = get_number("second")
        try:
            print(operation(x, y))
        except ZeroDivisionError:
            print("Can not divide by zero, try again")
    
    user_selection = input(menu_prompt)
    
    while user_selection.lower() != 'q':
        if user_selection in operations:
            selected_operation = operations[user_selection]
            run_selected_operation(selected_operation)
        else:
            print("Please enter a valid selection")
            user_selection = input(menu_prompt)
    
        user_selection = input(menu_prompt)
    
    print(menu_prompt)
    

How many English words
do you know?
Test your English vocabulary size, and measure
how many words do you know
Online Test
Powered by Examplum