2009-07-07 2 views
7

Я изучаю Python за последние несколько дней, и я написал этот фрагмент кода для оценки постфиксного выражения.Операторы Python

postfix_expression = "34*34*+" 

stack = [] 

for char in postfix_expression : 
    try : 
     char = int(char); 
     stack.append(char); 
    except ValueError: 
     if char == '+' : 
      stack.append(stack.pop() + stack.pop()) 
     elif char == '-' : 
      stack.append(stack.pop() - stack.pop()) 
     elif char == '*' : 
      stack.append(stack.pop() * stack.pop()) 
     elif char == '/' : 
      stack.append(stack.pop()/stack.pop()) 

print stack.pop() 

Есть ли способ избежать этого огромного блока if else? Как и в, существует ли модуль, который принимает математический оператор в строковой форме и вызывает соответствующий математический оператор или некоторую идиому python, которая делает это простым?

ответ

16

Модуль operator имеет функции, реализующие стандартные арифметические операторы. При этом, вы можете настроить отображение как:

OperatorFunctions = { 
    '+': operator.add, 
    '-': operator.sub, 
    '*': operator.mul, 
    '/': operator.div, 
    # etc 
} 

Тогда ваш основной цикл может выглядеть следующим образом:

for char in postfix_expression: 
    if char in OperatorFunctions: 
     stack.append(OperatorFunctions[char](stack.pop(), stack.pop())) 
    else: 
     stack.append(char) 

Вы хотите позаботиться о том, что операнды для вычитания и деления сбрасываются со стека в правильном порядке.

+1

Это круто, мне нравится Python. +1 – Boldewyn

0

Просто используйте eval наряду с генерацией строки:

postfix_expression = "34*34*+" 
stack = [] 
for char in postfix_expression: 
    if char in '+-*/': 
     expression = '%d%s%d' % (stack.pop(), char, stack.pop()) 
     stack.append(eval(expression)) 
    else: 
     stack.append(int(char)) 
print stack.pop() 

EDIT: сделал еще более хороший вариант без обработки исключений.

+0

Исходя из фона JS: Является ли eval() в Python плохим/медленным, как в JavaScript? – Boldewyn

+0

Я не знаю о медлительности. Это может быть опасно (например, небезопасно), если его не очень тщательно использовать, но здесь он абсолютно безопасен, поскольку проверяется все входные данные (целые числа или ограниченный набор символов). – DzinX

+0

@Boldewyn: eval обычно медленнее, чем эквивалентные решения, которые используют динамические возможности Python, поскольку при разборе и компиляции возникают существенные накладные расходы при каждом вызове eval(). Выполнение поиска в словаре и использование функций операторского модуля (OperatorFunctions ["+"] (2, 2)) примерно в 60 раз быстрее, чем использование eval (eval («2 + 2»)) – Miles

0
[untested] 
from operator import add, sub, mul, div 
# read the docs; this is a tiny part of the operator module 

despatcher = { 
    '+': add, 
    '-': sub, 
    # etc 
    } 

opfunc = despatcher[op_char] 
operand2 = stack.pop() 
# your - and/are bassackwards 
stack[-1] = opfunc(stack[-1], operand2) 
+0

@ чрезмерно усердный редактор: «despatcher» является принятой (хотя и предположительно менее распространенной) альтернативой «диспетчеру». Я вернул вашу редакцию обратно. Пожалуйста, оставьте это в покое. –

+0

@John: Является ли это одним из этих «британских англичан» против «американских английских вещей»? – PTBNL

+0

@PTBNL: Я не знаю. FWIW: количество попаданий в Google (миллионы, 3 символа): отправка 8.25, отправка 34.6, диспетчер 8.42, диспетчер 7.98. Интересная инверсия. –

Смежные вопросы