2
\$\begingroup\$

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()

Link to the code (pastebin).

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
\$\endgroup\$
2
\$\begingroup\$

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

in your main body:

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
\$\endgroup\$
  • \$\begingroup\$ Oh wow, never thought of using dictionaries. Thanks! \$\endgroup\$ – hope4tg Oct 7 '13 at 15:03
1
\$\begingroup\$

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.

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.