# Calculator that is part of a multipurpose program

I am currently working on a Python project. It is some sort of a hub, where you can do some cool but basic stuff, such as: setting timers, launching websites, doing basic math, ping and view source codes of URLs, and more.

I want to make this code just a little more compact. I especially want my math menu more compact because I feel there is a way of doing it. I just can't seem to figure it out.

…
elif userIn == ("math"):
op = str(input("    * Enter operation (+, -, *, /, exp, sqrt, log): "))
blank()
if op==("+") or op==("-") or op==("*") or op==("/") or op==("exp"):
input_1 = int(input("       * Enter first number:  "))
blank()
input_2 = int(input("       * Enter second number: "))
blank()
if op == ("+"):
print ("       > "+str(input_1 + input_2))
blank()
elif op == ("-"):
print ("       > "+str(input_1-input_2))
blank()
elif op == ("*"):
print ("       > "+str(input_1*input_2))
blank()
elif op == ("/"):
print ("       > "+str(input_1/input_2))
blank()
elif op == ("exp"):
print ("       > "+str(input_1**input_2))
blank()
elif op == ("sqrt"):
oneInput=int(input("        * Enter number: "))
blank()
print ("       > "+str(math.sqrt(oneInput)))
blank()
elif op == ("log"):
input_1 = int(input("       * Enter number:  "))
blank()
input_2 = int(input("       * Enter base: "))
blank()
print ("       > "+str(int((math.log(input_1, input_2)))))
blank()


Note: I have tried setting a basic for loop run through a list of operation symbols, and it would set the operation if the user op. was matched. But, as it turns out, I just couldn't use strings as math operators in the code itself.

opl=["+", "-", "*", "/"]
for i in range(len(opl)):
userInput1 (some way of setting op)     userInput2


I would suggest using a dict as switch-statement like structure.

First some global helper functions/data structures:

math_dict_binary = {'+': lambda a, b: a+b,
'-': lambda a, b: a-b,
# fill out the rest of you binary functions
}
math_dict_uniary = {'sqrt': math.sqrt,
# rest of you uniary
}

def get_input(str_prompt):
input = int(input("       * {}:  ".format(str_prompt)))
blank()
return input


elif userIn == ("math"):
op = str(input("    * Enter operation (+, -, *, /, exp, sqrt, log): "))
blank()
if op in math_dict_binary:
input_1 = get_input("Enter first number")
input_2 = get_input("Enter second number")
print( "    " + str(math_dict_binary[op](input_1, input_2)))
elif op in math_dict_uniary:
input_1 = get_input("Enter number")
print( "    " + str(math_dict_uniary[op](input_1)))
else:
print("Not a vlaid math option")
# deal with it

• Oh wow, never thought of using dictionaries. Thanks! – hope4tg Oct 7 '13 at 15:03

blank() was used at the end of every case so it can be used at the end of giant if block instead. Also, oneInput is unpythonic for a variable name use one_input. float has many magic methods. They have double underscores before and after the name. Here is a helpful list http://docs.python.org/3.2/library/operator.html. These methods can also be seen by typing dir(float). float was chosen due to division being used.

    operators=['+', '-', '*', '/', 'exp'];

user_operators=[
getattr(float, '__{}__'.format(i))
for i in ['add', 'sub', 'mul', 'truediv', 'pow']
];

opl=dict(zip(operators, user_operators));
output_prompt=' '*7+'> ';

if op in opl:
print( output_prompt+str(opl[op](float(input_1), input2)) );
#--snip-- other conditions for sqrt and log would go here
else:
raise ValueError('Unsupported operator {}'.format(op));
blank();


However, if division is removed from the lists operators and operations then int could be used and float(input_1) could just be input_1.

You may want to save opl[op] as a variable just to name it for easy reading. It is being used like a function.

• Oh so we add an exception handler as well? Seems fancy, i will try it out ASAP :) thanks for the answer :) – hope4tg Oct 7 '13 at 15:04