Welcome, guest | Sign In | My Account | Store | Cart

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.

Python, 58 lines
 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.

Created by Peter Shook on Thu, 12 Jul 2007 (PSF)
Python recipes (4591)
Peter Shook's recipes (1)

Required Modules

  • (none specified)

Other Information and Tasks