Базовый калькулятор Python
У меня есть молодой друг, который начинает изучать Python в школе, и попросил меня дать ему небольшое задание. Я ни в коем случае не учитель и не специалист по Python, но я согласился.
Сначала я подумал, что было бы интересно начать с небольшого анализа ввода операции, например:
Enter your operation : 3+3
Но это показалось ему немного подавляющим, поэтому мы договорились разделить его на три части (первое число, операнд и второе число).
Я сделал небольшое исправление, но считаю это неуклюжим, и цель упражнения - показать ему несколько хороших практик.
Итак, вот мой код:
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
Я бы хотел создать цикл, когда он number1или number2недействителен, floatпока пользователь не введет действительное значение, но я не нашел чистого способа сделать это. Я с радостью приму советы по этому поводу (хотя я знаю, что это не вопрос для этого Stack Exchange, хороший питонический способ сделать это было бы круто :)).
Ответы
Используйте больше функций
У вас есть функция calculate(), но если вы видите, что она делает гораздо больше, чем просто вычисляет, это делает ваш код неоправданно неуклюжим. Но есть очень простое решение - использовать больше функций. Что, если бы ваш основной цикл мог выглядеть как
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
Это упрощает поддержку вашей программы.
continue когда есть ошибка
try:
number1 = float(input("Enter the first number : "))
except ValueError:
print("Incorrect value")
exit()
Спросите себя, зачем программе завершаться, если пользователь вводит неверный ввод? Дай ему еще один шанс xD
Сохраняйте постоянный отступ
try:
number2 = float(input("Enter the second number : "))
except ValueError:
print("Incorrect value")
exit()
Старайтесь поддерживать последовательный отступ, поскольку вы использовали 4пробелы раньше, нет веских причин для использования 8позже, это может просто сбить с толку людей, которые прочитают код позже.
Кодовая логика 1
Давайте рассмотрим этот пример ввода
Enter the first number : 1
Enter the operation symbol (+,-,/,*,%) : I like python
Enter the second number : 2
Incorrect symbol
Ясно, что symbolэто неправильно. Почему мне пришлось вводить второй номер, чтобы узнать, что я ошибся при вводе symbol? Он должен был сразу сказать мне, что мой символ неправильный, чтобы я мог его исправить.
Просто переместите if symbol not in operandsоператор так, чтобы он располагался рядом с полем ввода.
eval
Eval в Python
Это будет самым большим улучшением в вашей программе, поскольку она преобразует около 10-15 строк кода в одну.
eval()Функция вычисляет заданное выражение, если выражение является юридическим заявлением Python, он будет выполнен.
Звучит знакомо, разве мы не оцениваем в основном простые выражения?
Используя eval, ваша расчетная часть будет выглядеть как
result = eval(f"{number1}{operand}{number2}")
Пример, number1 = 5,number2 = 10, operand = '+'
Вот что в основном и происходит
result = eval("5+10")
Финал
Вот код с улучшениями
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()
Это альтернатива вашему коду, он немного сложнее, но при этом более читабелен. Мне удалось сделать петлю, но за ней сложно уследить. Сожалею.
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()
Подсказки:
Разбейте вещи на функции:
Функции просто контейнеры для кода , которые могут быть выполнены, функции должны сделать ОДИН и только ОДИН вещи больше функций здесь .
Пожалуйста, попробуйте прокомментировать свой код, это облегчит чтение и редактирование.
Эта функция
def calc():
x = 1
y = 12
return (((x+y)/x)**y)+(3*x+4*y) # Please don't write like this in any case
было бы намного лучше с объяснением или что происходит
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
Используйте строки f (для этого требуется Python 3.6 и выше)
f строки используются так
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))
Попробуйте выделить свой код
Поверьте, это облегчает чтение и понимание вашего кода.
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