2009-07-07 4 views
7

Sto imparando Python negli ultimi giorni e ho scritto questo pezzo di codice per valutare un'espressione postfissa.Operatori 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() 

C'è un modo per evitare quell'enorme blocco se non altro? Come in, c'è un modulo che prende un operatore matematico nella stringa e invoca il corrispondente operatore matematico o qualche idioma python che rende questo semplice?

risposta

16

Il modulo operator ha funzioni che implementano gli operatori aritmetici standard. Con questo, è possibile impostare una mappatura simile:

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

Allora il vostro ciclo principale può essere simile a questa:

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

Si vuole fare attenzione a garantire che gli operandi per sottrazione e divisione vengono estratti dalla pila nell'ordine corretto.

+1

È fantastico, mi piace Python. +1 – Boldewyn

0

Basta usare eval insieme con la generazione stringa:

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: ha fatto una versione ancora più bello, senza la gestione delle eccezioni.

+0

Proveniente da uno sfondo JS: Eval() in Python è brutto/lento come in JavaScript? – Boldewyn

+0

Non conosco la lentezza. Può essere pericoloso (cioè pericoloso) se non viene usato con molta attenzione, ma qui è perfettamente sicuro dato che tutti gli input sono controllati (interi o un set di caratteri limitato). – DzinX

+0

@Boldewyn: eval è generalmente più lento delle soluzioni equivalenti che sfruttano le funzionalità dinamiche di Python, poiché c'è un sovraccarico sostanziale nell'analisi e nella compilazione ogni volta che viene chiamato eval(). Fare una ricerca nel dizionario e utilizzare le funzioni del modulo operatore (Funzioni operatore ["+"] (2, 2)) è circa 60 volte più veloce rispetto all'utilizzo di 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

@ editor troppo zelante: "dispatcher" è un'alternativa accettata (sebbene presumibilmente meno comune) a "dispatcher". Ho ripristinato la tua modifica. Per favore lascia stare. –

+0

@John: È uno di quegli "inglesi inglesi" contro "cose ​​inglesi americane? – PTBNL

+0

@PTBNL: non lo so FWIW: numero di hit di Google (milioni, 3 cifre): invio 8.25, invio 34.6, dispatcher 8.42, dispatcher 7.98 Inversione interessante. –