3
\$\begingroup\$

I want to start learning python for fun and so I could dig into machine learning projects later in the future maybe.

I started off with a small calculator project just to get the hang of the language and the IDE and wanted to get some feedback. I prefer progressing in baby steps and get some useful tips even though this is a really small project. Any comment would be great (regarding the code itself, code standards, etc)

Here's the code:

calculator.core

MULTIPLY_OPERATOR = '*'
DIVIDE_OPERATOR = '/'
SUBTRACTION_OPERATOR = '-'
PLUS_OPERATOR = '+'
INVALID_CALCULATION_CODE = -1
def summation(first_operand, second_operand):
 """
 Summing the two operands
 :param first_operand: first operand
 :param second_operand: second operand
 :return: sum of both operands, success indication
 """
 return first_operand + second_operand, True
def subtraction(first_operand, second_operand):
 """
 subtraction of second operand from the first
 :param first_operand: first operand
 :param second_operand: second operand
 :return: subtraction of second operand from the first, success indication
 """
 return first_operand - second_operand, True
def multiply(first_operand, second_operand):
 """
 multiply operands
 :param first_operand: first operand
 :param second_operand: second operand
 :return: multiplication of first and second operands, success indication
 """
 return first_operand * second_operand, True
def divide(first_operand, second_operand):
 """
 divide first operand by the second
 :param first_operand: first operand
 :param second_operand: second operand
 :return: divide result, success indication
 """
 if second_operand == 0:
 return INVALID_CALCULATION_CODE, False
 return first_operand / second_operand, True
SUPPORTED_OPERATORS_DICT = {
 "+": summation,
 "-": subtraction,
 "/": divide,
 "*": multiply
}

calculator_console

from calculator_core import *
INVALID_COMMAND_CODE = -1
EXIT_COMMAND = "exit"
def find_operator_index(command):
 """
 Returns the index of the operator in the command
 :param command: The string command from the user
 :return: The index of the operator
 """
 for charIndex in range(len(command)):
 if command[charIndex] in SUPPORTED_OPERATORS_DICT.keys():
 return charIndex
 return INVALID_COMMAND_CODE
def print_error_message(code):
 """
 prints error message
 :param code: error code
 :return:
 """
 if code == INVALID_COMMAND_CODE:
 print "The command you entered is in valid. Please try again.\n"
 elif code == INVALID_CALCULATION_CODE:
 print "The calculation is in valid. Please try again\n"
def float_try_parse(value):
 """
 gets a string and tries to convert it to int
 :param value: string to be converted
 :return: integer value and success indication
 """
 try:
 return float(value), True
 except ValueError:
 return value, False
def take_commands():
 """
 Process a command from the user and outputs the result to the console
 :return:
 """
 while True:
 command = raw_input("Please enter a command\n")
 # Exit
 if command == EXIT_COMMAND:
 return
 # Processing a computing command
 operator_index = find_operator_index(command)
 # Invalid operator index
 if operator_index == INVALID_COMMAND_CODE:
 print_error_message(INVALID_COMMAND_CODE)
 continue
 # Parsing first operand
 first_operand, success = int_try_parse(command[0:operator_index])
 if not success:
 print_error_message(INVALID_COMMAND_CODE)
 continue
 # Parsing second operand
 second_operand, success = int_try_parse(command[operator_index+1:])
 if not success:
 print_error_message(INVALID_COMMAND_CODE)
 continue
 # Executing The command
 result, success_indication = SUPPORTED_OPERATORS_DICT[command[operator_index]](first_operand, second_operand)
 if not success_indication:
 print_error_message(INVALID_CALCULATION_CODE)
 else:
 print("{}{}".format(result, '\n'))
if __name__ == '__main__':
 """
 The main function
 """
 take_commands()

calculator_gui

from tkinter import *
from calculator_core import *
fields = 'First Operand', 'Second Operand'
variables = {'curr_operator': "+"}
def float_try_parse(value):
 """
 gets a string and tries to convert it to int
 :param value: string to be converted
 :return: integer value and success indication
 """
 try:
 return float(value), True
 except ValueError:
 return value, False
def compute(entries):
 """
 Computes the result of the given computation
 :param entries: Form entries
 :return:
 """
 values = []
 for entry in entries:
 value = entry[1].get()
 value, success = float_try_parse(value)
 if not success:
 return
 values.append(value)
 result, success = SUPPORTED_OPERATORS_DICT[variables['curr_operator']](values[0], values[1])
 if not success:
 return
 result_label['text'] = result
def makeform(root, fields):
 """
 Creating the form fields
 :param root: The form root
 :param fields: Fields to be created
 :return: The created form entries
 """
 entries = []
 for field in fields:
 row = Frame(root)
 lab = Label(row, width=15, text=field, anchor='w')
 ent = Entry(row)
 row.pack(side=TOP, fill=X, padx=5, pady=5)
 lab.pack(side=LEFT)
 ent.pack(side=RIGHT, expand=YES, fill=X)
 entries.append((field, ent))
 return entries
def changed(*args):
 """
 Tracks changes of the operator
 :param args:
 :return:
 """
 variables['curr_operator'] = s.get()
if __name__ == '__main__':
 root = Tk()
 ents = makeform(root, fields)
 s = StringVar()
 s.set('+')
 s.trace('w', changed)
 om = OptionMenu(root, s, '+', '-', '*', '/')
 om.pack()
 b1 = Button(root, text='Compute',
 command=(lambda e=ents: compute(e)))
 b1.pack(side=LEFT, padx=5, pady=5)
 b2 = Button(root, text='Quit', command=root.quit)
 b2.pack(side=LEFT, padx=5, pady=5)
 result_label = Label(root, text="")
 result_label.pack()
 root.mainloop()
200_success
146k22 gold badges192 silver badges481 bronze badges
asked Mar 2, 2019 at 14:10
\$\endgroup\$
2
  • \$\begingroup\$ Is this Python 2 or 3? From the prints it looks like Python 3, but raw_input exists only in Python 2. We have the tags python-2.x and python-3.x if your code only works in one of the two versions (in that case add them in addition to the python tag). \$\endgroup\$ Commented Mar 2, 2019 at 14:14
  • 1
    \$\begingroup\$ Sorry I forgot to add this tag, yes I accidently wrote it in python 2.. In the next program I will use python 3 \$\endgroup\$ Commented Mar 2, 2019 at 14:40

1 Answer 1

2
\$\begingroup\$

So, your doc strings look fine. I would like to point out few things

1-) In your core class, you are returning True along with the calculated value but you don't make any validations (Except the division function) so it is always True. You could add a validation function (Maybe as a decorator) and validate the given inputs type's (For example there will be an error if you try to sum up a string and integer

2-) (from calculator_core import *) in your calculator_console script is not really a best practice since it could cause namespace collisions, you could just import it like , 'import calculator_core'

3-) In your 'find_operator_index' function you iterate and find the operator's index and after that you use it for slicing. I would rather find the operator itself and split it by the operator in that case and I would use a comprehension. Like

operator = [operator_char for operator_char in command if operator_char in SUPPORTED_OPERATORS_DICT.keys()]

And validate it like;

if len(operator) > 0:
 #there is an operator
answered Mar 2, 2019 at 14:46
\$\endgroup\$

You must log in to answer this question.