Использование словаря в качестве оператора switch в Python

Я пытаюсь сделать простой калькулятор в Python, используя словарь. Здесь мой код:

def default():
    print "Incorrect input!"

def add(a, b):
    print a+b

def sub(a, b):
    print a-b

def mult(a, b):
    print a*b

def div(a, b):
    print a/b

line = raw_input("Input: ")
parts = line.split(" ")
part1 = float(parts[0])
op = parts[1];
part3 = float(parts[2])

dict = {
    '+': add(part1, part3),
    '-': sub(part1, part3),
    '*': mult(part1, part3),
    '/': div(part1, part3)
    }

try:
    dict[op]
except KeyError:
    default()

но все функции активированы. В чем проблема?

Ответ 1

Определите свой словарь как пары формы str : function:

my_dict = {'+' : add, 
           '-' : sub, 
           '*' : mult, 
           '/' : div}

И затем, если вы хотите вызвать операцию, используйте my_dict[op] для получения функции, а затем передайте ее с соответствующими параметрами:

 my_dict[op] (part1, part3)
|___________|
      |
  function (parameters)

Примечание. Не используйте встроенные имена Python в качестве имен переменных, иначе вы скроете его реализацию. Используйте my_dict вместо dict, например.

Ответ 2

Это происходит потому, что, когда словарь заполняется, он выполняет каждую операцию с операндами, и в конце вы вызываете dict[op], который содержит None и ничего не делать с ним.

Что происходит:

# N.B.: in case this is not clear enough, 
#       what follows is the *BAD* code from the OP
#       with inline explainations why this code is wrong

dict = {
    # executes the function add, outputs the result and assign None to the key '+'
    '+': add(part1, part3), 
    # executes the function sub, outputs the result and assign None to the key '-'
    '-': sub(part1, part3),
    # executes the function mult, outputs the result and assign None to the key '*'
    '*': mult(part1, part3),
    # executes the function div, outputs the result and assign None to the key '/'
    '/': div(part1, part3)
    }

try:
    # gets the value at the key "op" and do nothing with it
    dict[op]
except KeyError:
    default()

поэтому вы получаете все выходы, и ничего не происходит в вашем блоке try.

Возможно, вы захотите:

dict = {
    '+': add,
    '-': sub,
    '*': mult,
    '/': div
    }

try:
    dict[op](part1, part3)
except KeyError:
    default()

но, как подсказывает @christian, вы не должны использовать зарезервированные имена python в качестве имен переменных, что может привести к неприятностям. И еще одно улучшение я советую вам todo - напечатать результат один раз и выполнить функции lambdas:

d = {
    '+': lambda x,y: x+y,
    '-': lambda x,y: x-y,
    '*': lambda x,y: x*y,
    '/': lambda x,y: x/y
    }

try:
    print(d[op](part1, part3))
except KeyError:
    default()

который вернет результат и распечатает его