Calculadora básica de python
Tengo un joven amigo que está empezando a aprender Python en la escuela y me pidió que le diera una pequeña tarea. De ninguna manera soy un profesor ni un experto en Python, pero acepté.
Al principio pensé que sería divertido comenzar analizando un poco la entrada de la operación, como:
Enter your operation : 3+3
Pero le pareció un poco abrumador, así que acordamos separarlo en tres partes (primer número, operando y segundo número).
Hice una pequeña corrección pero me parece torpe y el objetivo del ejercicio es mostrarle algunas buenas prácticas.
Entonces aquí está mi código:
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
Hubiera querido hacer un bucle cuando number1o number2no sea válido floathasta que el usuario ingrese un valor válido, pero no encontré una manera limpia de hacerlo. Con mucho gusto aceptaría consejos sobre esto (aunque sé que esta no es una pregunta para este Stack Exchange, una buena forma Pythonic de hacer esto sería genial :)).
Respuestas
Usa más funciones
Tiene una función calculate(), pero si ve que hace mucho más que calcular, esto hace que su código se vea irrazonablemente torpe. Pero hay una solución muy simple, use más funciones. ¿Y si su bucle principal pudiera verse como
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
Esto facilita el mantenimiento de su programa.
continue cuando hay un error
try:
number1 = float(input("Enter the first number : "))
except ValueError:
print("Incorrect value")
exit()
Pregúntese, ¿por qué terminaría un programa si el usuario ingresa una entrada no válida? Dale otra oportunidad xD
Mantenga una sangría constante
try:
number2 = float(input("Enter the second number : "))
except ValueError:
print("Incorrect value")
exit()
Trate de mantener una sangría consistente, ya que ha usado 4espacios antes, no hay una buena razón para usarlos 8más tarde, podría confundir a las personas que lean el código más tarde.
Lógica de código 1
Consideremos esta entrada de muestra
Enter the first number : 1
Enter the operation symbol (+,-,/,*,%) : I like python
Enter the second number : 2
Incorrect symbol
Claramente, symbolestá mal. ¿Por qué tuve que ingresar el segundo número, solo para descubrir que cometí un error al ingresar el symbol? Debería haberme dicho de inmediato que mi símbolo era incorrecto, por lo que podría haberlo corregido.
Simplemente mueva el if symbol not in operandsenunciado para que quede junto a la entrada.
eval
Evaluar en Python
Esta sería la mayor mejora en su programa, ya que convierte entre 10 y 15 líneas de código en una.
La
eval()función evalúa la expresión especificada, si la expresión es una declaración de Python legal, se ejecutará.
Eso suena familiar, ¿no estamos evaluando básicamente expresiones simples?
Usando eval, su parte de cálculo se vería así
result = eval(f"{number1}{operand}{number2}")
Ejemplo, number1 = 5,number2 = 10, operand = '+'
Esto es lo que básicamente está pasando
result = eval("5+10")
Final
Aquí está el código con las mejoras.
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()
Esta es una alternativa a su código, es un poco más complejo pero también es más legible. Me las arreglé para hacer el bucle, pero es un poco difícil de seguir. Lo siento.
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()
Consejos:
Divida las cosas en funciones:
Las funciones son solo contenedores para el código que se puede ejecutar, las funciones DEBEN hacer UNA y solo UNA cosa más en las funciones aquí .
Intente comentar su código, lo hace más fácil de leer y editar.
Esta función
def calc():
x = 1
y = 12
return (((x+y)/x)**y)+(3*x+4*y) # Please don't write like this in any case
sería mucho mejor con una explicación o lo que está pasando
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
Use f strings (esto requiere python 3.6 y superior)
f cadenas se usan así
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))
Intenta espaciar tu código
Créame, esto hace que su código sea más fácil de leer y comprender.
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