class Menu:
    def __init__(self, start):                  # inherited constructor
        self.menu = start                       # 'start' menu required here

    def __getitem__(self, index):               # index a wrapped menu
        return self.menu[index]                 # __getattr__ doesn't index

    def __setitem__(self, index, value):        # set a menu's key/index
        self.menu[index] = value

    def __getattr__(self, name):                # other 'menu' attributes
        return getattr(self.menu, name)         # keys, append, sort...

    def run(self, prompt='?'):                  # a 'real' method
        try:
            while 1:                            # common interactive loop
                print '\n\tMENU...'
                self.showOptions()
                command = raw_input(prompt)
                try:
                    flag = self.runCommand(command)
                except (IndexError, KeyError):
                    print "what: '%s'?" % command 
                else:
                    if flag: break
        except EOFError: pass                   # ctrl-d still exits all


class DictMenu(Menu): 
    def __init__(self, menu=None): 
        Menu.__init__(self, menu or {})         # new dict each time

    def __add__(self, other):                   # on: 'menu + other'
        new = DictMenu()                        # make a new instance
        for key in self.keys():  
            new[key] = self[key]                # copy 'self' dict
        for key in other.keys():  
            new[key] = other[key]               # add other dict
        return new

    def extend(self, other):                    # change menu in-place
        for key in other.keys():
            self[key] = other[key]              # uses __setitem__

    def showOptions(self):                      # more 'real' methods
        options = self.keys()                   # uses __getattr__
        options.sort()
        for cmd in options: print '\t\t' + cmd

    def runCommand(self, cmd): 
        return self[cmd]()                      # uses __getitem__


class ListMenu(Menu):
    def __init__(self, menu=None): 
        Menu.__init__(self, menu or [])         # new list each time

    def __add__(self, other):                   # on: 'menu + other'
        return ListMenu(self.menu + other)      # make a new instance

    def extend(self, other):                    # change menu in-place
        self.append(other)                      # uses __getattr__

    def showOptions(self):
        i = 0                                   # 'in' uses __getitem__
        for name, func in self:
            print '\t\t%d) %s' % (i, name); i=i+1

    def runCommand(self, cmd):
        try:
            index = eval(cmd)                   # convert string to number
        except: 
            raise IndexError
        return self[index][1]()                 # uses __getitem__
