4
\$\begingroup\$

As a beginner I wrote my first program (calculator) with Python and as far as functionality is concerned it just works fine but I have some concerns about one thing at the end of the code. Under CalculateAgain() in the if statement, Calculate() is without the return statement. If I used it, it would just run the function one time and then it exits the program. That's why i left it without the statement. Is this ok or should I change something?

#Choose the operation
def OperationType():

    while True:

        Type = input('What type of operation do you want? +, -, *, /: \n')

        if Type in ('+', '-', '*', '/'):
            return Type
        else:
            print('Invalid input')


#Enter the first number
def InputFirstNumber():

    while True:
        try:
            firstNumber = float(input('Enter your first number: '))
            return firstNumber
        except ValueError:
            print ('Please enter a number')


#Enter the second number
def InputSecondNumber():

    while True:
        try:
            secondNumber = float(input('Enter your second number: '))
            return secondNumber
        except ValueError:
            print ('Please enter a number')


#Calculating
def Calculate():

    Type = OperationType()
    firstNumber = InputFirstNumber()
    secondNumber = InputSecondNumber()

    if Type == '+':
        print('{} + {} = '.format(firstNumber, secondNumber), firstNumber + secondNumber)

    elif Type == '-':
        print('{} - {} = '.format(firstNumber, secondNumber), firstNumber - secondNumber)

    elif Type == '*':
        print('{} * {} = '.format(firstNumber, secondNumber), firstNumber * secondNumber)

    elif Type == '/':
        print('{} / {} = '.format(firstNumber, secondNumber), firstNumber / secondNumber)

    else:
        print('Input not valid')


Calculate()

#Asks if the User want to calculate again
def CalculateAgain():

    while True:

        calculating_again = input('Do you want to calculate again? Y/N \n')


        if calculating_again in ('Y','y'):
            Calculate()

        elif calculating_again in ('N','n'):
            print('Quitting the program')
            break

        else:
            print('Not a valid answer')

CalculateAgain()
\$\endgroup\$
3
  • \$\begingroup\$ Can you fix the indentation? As of right now this isn't working code, which is deemed off topic for this site. \$\endgroup\$ – Linny May 7 '20 at 14:44
  • \$\begingroup\$ Now it should work \$\endgroup\$ – PickleRick May 7 '20 at 14:55
  • \$\begingroup\$ I would suggest that you make Calculate return a boolean value -- True if the calculator should continue, false if it should exit. Then call that function in Calculate. Python does not have an explicit repeat .. until construct but you can create the equivalent by using the same pattern you have used in all your input routines. Just wrap calculate in a while True: block, and if notCalculateAgain(): break Your program only need call Calculate() to run. \$\endgroup\$ – gview May 8 '20 at 4:40
1
\$\begingroup\$

Here's a minor modification that eliminates the need to call CalculateAgain() after Calculate().

#Choose the operation
def OperationType():

    while True:

        Type = input('What type of operation do you want? +, -, *, /: \n')

        if Type in ('+', '-', '*', '/'):
            return Type
        else:
            print('Invalid input')


#Enter the first number
def InputFirstNumber():

    while True:
        try:
            firstNumber = float(input('Enter your first number: '))
            return firstNumber
        except ValueError:
            print ('Please enter a number')


#Enter the second number
def InputSecondNumber():

    while True:
        try:
            secondNumber = float(input('Enter your second number: '))
            return secondNumber
        except ValueError:
            print ('Please enter a number')


#Asks if the User want to calculate again
def CalculateAgain():

    while True:

        calculating_again = input('Do you want to calculate again? Y/N \n')


        if calculating_again in ('Y','y'):
            return True

        elif calculating_again in ('N','n'):
            print('Quitting the program')
            return False

        else:
            print('Not a valid answer')


#Calculating
def Calculate():
    while True:
        Type = OperationType()
        firstNumber = InputFirstNumber()
        secondNumber = InputSecondNumber()

        if Type == '+':
            print('{} + {} = '.format(firstNumber, secondNumber), firstNumber + secondNumber)

        elif Type == '-':
            print('{} - {} = '.format(firstNumber, secondNumber), firstNumber - secondNumber)

        elif Type == '*':
            print('{} * {} = '.format(firstNumber, secondNumber), firstNumber * secondNumber)

        elif Type == '/':
            print('{} / {} = '.format(firstNumber, secondNumber), firstNumber / secondNumber)

        else:
            print('Input not valid')

        if not CalculateAgain():
          break

Calculate()
\$\endgroup\$
3
\$\begingroup\$

This code is broken into multiple unnecessary functions. Below is all thats needed:

operations = {
    "+": lambda x, y: x + y,
    "-": lambda x, y: x - y,
    "*": lambda x, y: x * y,
    "/": lambda x, y: x / y
}

def calculate():

    # Get numbers #
    one, two = input("Enter two numbers separated by a space: ").split()

    while operator := input("Enter an operator: + - * /"):
        if operator in ["+", "-", "*", "/"]:
            print(operations[operator](int(one), int(two)))
            return

Getting multiple values from input

Instead of prompting for each number, simply ask for two numbers separated by a space then split the input with a given delimiter, by default a space. .split returns a list, and since you only anticipate two values, can assign the output to one, two.

Walrus Operator

If you're using python-3.8, you can utilize the walrus operator, also called assignment expressions. It allows you to assign and return a value in an expression. This reduces the need to define a variable before the loop and use it.

Checking in

I do believe using a list/tuple instead of a string when checking in this particular case because it can catch some invalid input. A catch such as if operator in "+-*/":, it will allow "+-" as a valid operator, which we don't want. So good job there.

Lambdas

I've decided to use lambdas here because it's much easier to store them in a dictionary and then simply retrieve the value from the dictionary with the operator. If you want to learn more about how lambdas work, this Google Search brings up a plethora of sources that can explain the concept much better than I can.

\$\endgroup\$
2
  • \$\begingroup\$ Great answer. With that said, the poster did state in advance that they are a beginning programmer, and had a specific request in regards to their existing code. I do think your contribution could be very valuable, but I expect that a Lambda is a challenging concept, and you could expand on your Lambda section, and better explain what a Lambda is, and how specifically this makes your code work. +1 from me though ;) \$\endgroup\$ – gview May 9 '20 at 0:50
  • \$\begingroup\$ @gview I agree, and have expanded upon my lambda section. \$\endgroup\$ – Linny May 9 '20 at 1:51

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.