Calculatrice python de base

Oct 20 2020

J'ai un jeune ami à moi qui commence à apprendre le Python à l'école et m'a demandé de lui confier une petite mission. Je ne suis en aucun cas un enseignant ni un expert Python, mais j'ai accepté.

Au début, j'ai pensé que ce serait amusant de commencer par un peu d'analyse de l'entrée de l'opération, comme:

Enter your operation : 3+3

Mais cela lui a semblé un peu écrasant, nous avons donc accepté de le séparer en trois parties (premier numéro, opérande et deuxième numéro).

J'ai fait une petite correction mais je trouve ça maladroit et le but de l'exercice est de lui montrer quelques bonnes pratiques.

Alors voici mon code:

calculate = True
while calculate:
    try:
        number1 = float(input("Enter the first number : "))
    except ValueError:
            print("Incorrect value")
            exit()
    symbol = input("Enter the operation symbol (+,-,/,*,%) : ")
    try:
        number2 = float(input("Enter the second number : "))
    except ValueError:
            print("Incorrect value")
            exit()
    operande = ["+", "-", "*", "/", "%"]
    resSentence = "Result of operation \"{} {} {}\" is :".format(number1, symbol, number2)
    if symbol not in operande:
        print("Incorrect symbol")
    elif symbol == "+":
        print(resSentence, number1 + number2)
    elif symbol == "-":
        print(resSentence, number1 - number2)
    elif symbol == "*":
        print(resSentence, number1 * number2)
    elif symbol == "/":
        print(resSentence, number1 / number2)
    elif symbol == "%":
        print(resSentence, number1 % number2)
    restart = input("Do you want to do another calcul (Y/n) ? ")
    while restart.lower() != "y" and restart.lower() != "n":
        print(restart.lower(), restart.lower(), restart.lower()=="n")
        restart = input("Please, enter \"y\" to continue or \"n\" to exit the program : ")
    if restart.lower() == "n":
        calculate = False

J'aurais voulu faire une boucle quand number1ou number2n'est pas valide floatjusqu'à ce que l'utilisateur entre une valeur valide, mais je n'ai pas trouvé de moyen propre de le faire. J'accepterais volontiers des conseils à ce sujet (même si je sais que ce n'est pas une question pour ce Stack Exchange, une bonne façon Pythonic de le faire serait cool :)).

Réponses

9 AryanParekh Oct 21 2020 at 04:59

Utiliser plus de fonctions

Vous avez une fonction calculate(), mais si vous voyez qu'elle fait beaucoup plus que simplement calculer, cela rend votre code déraisonnablement maladroit. Mais il existe une solution très simple, utiliser plus de fonctions. Et si votre boucle principale pouvait ressembler à

while True:
    number1,number2,operand = take_input()
    result = calculate(number1,number2,operand)
    print(f"Answer : {numebr1} {operand} {number2} = {result}")
    if input("Do you want to play again? (y/n): ").lower() == 'n':
        break 

Cela facilite la maintenance de votre programme.

continue quand il y a une erreur

try:
    number1 = float(input("Enter the first number : "))
except ValueError:
        print("Incorrect value")
        exit()

Posez-vous la question, pourquoi un programme se terminerait-il si l'utilisateur entre une entrée non valide? Donnez-lui une autre chance xD

Maintenir une indentation cohérente

try:
    number2 = float(input("Enter the second number : "))
except ValueError:
            print("Incorrect value")
            exit()

Essayez de maintenir une indentation cohérente, puisque vous avez utilisé des 4espaces plus tôt, il n'y a aucune bonne raison de les utiliser 8plus tard, cela risque de dérouter les personnes qui liront le code plus tard.

Code logique 1

Considérons cet exemple d'entrée

Enter the first number : 1
Enter the operation symbol (+,-,/,*,%) : I like python
Enter the second number : 2
Incorrect symbol

Clairement, symbolc'est faux. Pourquoi ai-je dû entrer le deuxième numéro, juste pour savoir que j'avais fait une erreur en entrant le symbol? Cela aurait dû me dire tout de suite que mon symbole était incorrect, alors j'aurais pu le corriger.

Déplacez simplement l' if symbol not in operandsinstruction pour qu'elle se trouve juste à côté de l'entrée.

eval

Eval en Python

Ce serait la plus grande amélioration de votre programme, car il convertit environ 10 à 15 lignes de code en une seule.

La eval()fonction évalue l'expression spécifiée, si l'expression est une instruction Python légale, elle sera exécutée.

Cela semble familier, n'évaluons-nous pas essentiellement des expressions simples?

En utilisant eval, votre partie de calcul ressemblerait à

result = eval(f"{number1}{operand}{number2}")

Exemple, number1 = 5,number2 = 10, operand = '+'

C'est ce qui se passe fondamentalement

result = eval("5+10")

Final

Voici le code avec les améliorations

def take_input():
    err_msg = "Invalid input"
    operands = ['+','-','*','/','%']
    try:
        num1 = float(input("Enter number 1: "))
    except Exception:
        print(err_msg)
        return take_input()
    try:
        num2 = float(input("Enter number 2: "))
    except Exception:
        print(err_msg)
        return take_input()

    print("Operands: " + ', '.join(x for x in operands))
    try:
        operand = input("Enter operand: ")
    except Exception:
        print(err_msg)
        return take_input()

    if operand not in operands:
        print(err_msg)
        return take_input()

    return num1,num2,operand

def calculate(num1,num2,operand):
    return eval(f"{num1}{operand}{num2}")


def mainloop():
    while True:
        num1,num2,operand = take_input()
        result = calculate(num1,num2,operand)
        print(f"Answer: {result}")
        if input("Do you want to play again? (y/n): ").lower() == 'n':
            break

mainloop()
5 Deep_Thoughts Oct 20 2020 at 21:54

C'est une alternative à votre code, c'est un peu plus complexe mais c'est aussi plus lisible. J'ai réussi à faire la boucle mais c'est un peu difficile à suivre. Désolé.

running = True
# Break Things up into functions each function does one single thing

def calculate(inputOne, operand, inputTwo):
    """
    Calculates inputOne operand and inputTwo
    """

    if operand == "+":
        return inputOne + inputTwo
    elif operand == "-":
        return inputOne - inputTwo
    elif operand == "*":
        return inputOne * inputTwo
    elif operand == "/":
        return inputOne / inputTwo
    elif operand == "%":
        return inputOne % inputTwo

def askInput():
    """
    Asks for a number until a number is given checks if each one is valid
    """

    isValid = [False, False, False] # none of the numbers are validated yet
    number1, symbol, number2 = ["", "", ""]
    
    # Here is a good implementation of the loop, it is kind of complex though
    while True:
        try:
            if not isValid[0]: # Asks for number1 if it is not valid
                number1 = int(input("Enter the first number : "))
                isValid[0] = True

            if not isValid[1]: # This is added functionality because there was a loophole in your program
                symbol = input("Enter the operation symbol (+,-,/,*,%) : ") # use tuples whenever possible
                supportedOperands = ("+", "-", "/", "*", "%")

                if symbol not in supportedOperands:
                    raise ValueError

                isValid[1] = True

            if not isValid[2]: # Asks for number2 if it is not valid
                number2 = int(input("Enter the second number : "))
                isValid[2] = True
            break
        
        except ValueError:
            continue # this just restarts the whole thing
    
    return number1, symbol, number2



def continueApp():
    """
    Checks if the input to restart is valid
    """
    restart = input("Do You want to do another calculation (Y/n) ? ").lower()

    while True:
        if restart == "y":
            return True
        elif restart == "n":
            return False
        else:
            restart = input("Please, enter \"y\" to continue or \"n\" to exit the program : ").lower()

while running:

    numberOne, operand, numberTwo = askInput()
    answer = calculate(numberOne, operand, numberTwo)
    resSentence = f"Result of operation {numberOne} {operand} {numberTwo} is : {answer}"
    print(resSentence)

    if continueApp():
        pass
    else:
        running = False
exit()


Conseils:

  • Divisez les choses en fonctions:

Les fonctions ne sont que des conteneurs pour le code qui peuvent être exécutées, les fonctions DOIVENT faire UN et seulement UNE chose de plus sur les fonctions ici .

  • Veuillez essayer de commenter votre code, il est plus facile à lire et à modifier.

Cette fonction

def calc():
    x = 1
    y = 12
    return (((x+y)/x)**y)+(3*x+4*y) # Please don't write like this in any case

serait beaucoup mieux avec une explication ou ce qui se passe

def calc():
    """
    Accepts: Nothing
    Does: Adds X and Y, then divides it by X to the power of Y
          then it adds  it to X multiplied by three and 4 multiplied by Y
    Returns: integer (the result of Does) ^^^^^
    """
    x = 1
    y = 12
    return ((x+y)/x**y)+(3*x+4*y) # Again, please don't write code like this
  • Utilisez des chaînes f (cela nécessite python 3.6 et supérieur)

Les chaînes f sont utilisées comme ceci

value = "12"
print(f"Number {value} is an example of an f string") 

# Versus

print("Number {} is an example of an f string".format(value))
  • Essayez d'espacer votre code

Croyez-moi, cela rend votre code plus facile à lire et à comprendre.

def calc():
    """
    Accepts: Nothing
    Does: Adds X and Y, then divides it by X to the power of Y
          then it adds  it to X multiplied by three and 4 multiplied by Y
    Returns: integer (the result of Does) ^^^^^
    """
    x = 1
    y = 12
    ans = (x + y) / (x ** y)
    ans += (3 * x) + (4 * y) # just adds ans to the right side of the operator
    return ans