You can make your dispatch tables easier to maintain by using a decorator to assign a key to each method you wish to save in the dictionary for the dispatch table.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | class RPN_Evaluator(object):
def __init__(self):
self.stack = []
def push(self, x):
self.stack.append(x)
def pop(self):
return self.stack.pop() if self.stack else 0
def result(self):
return self.stack[:]
operations = {}
assign = lambda d, k: lambda f: d.setdefault(k, f)
@assign(operations, '+')
def plus(self, a, b):
return a + b
@assign(operations, '-')
def minus(self, a, b):
return a - b
@assign(operations, '*')
def mult(self, a, b):
return a * b
@assign(operations, '/')
def div(self, a, b):
return a / b
def dispatch(self, k, *args, **kwds):
try:
method = self.operations[k].__get__(self, type(self))
except KeyError:
assert k in self.operations, "invalid operation: " + repr(k)
return method(*args, **kwds)
def eval(self, rpn):
for x in str(rpn).split():
try:
value = int(x)
except ValueError:
b = self.pop()
a = self.pop()
value = self.dispatch(x, a, b)
self.push(value)
return self.result()
calc = RPN_Evaluator()
calc.eval('2 2 +')
calc.eval('1 2 3 4 * * *')
calc.eval('1 2 + 3 4 + 5 + +')
calc.eval('5 5 1 + * 2 /')
print calc.result() # [4, 24, 15, 15]
|
When you have a dispatch table with a very large number of methods, it's nice to have the key value right next to the method.
As of Python 2.2, you may use the __get__ method of a function to turn it into a bound method.
Tags: shortcuts