Search code examples
pythonsparse-array

Storing functions in a sparse array with Python


I have a relatively large enum wherein each member represents a message type. A client will receive a message containing the integer value associated with the msg type in the enum. For each msg type there will be an individual function callback to handle the msg.

I'd like to make the lookup and dispatching of the callback as quick as possible by using a sparse array (or vector) in which the enum value maps to the index of the callback. Is this possible in Python given arrays can't hold function types?

#pseudo code for 'enum'
class MsgType(object):
    LOGIN, LOGOUT, HEARTBEAT, ... = range(n)

#handler class
class Handler(object):
    def handleMsg(self, msg):
        #dispatch msg to specific handler

    def __onLogin(self, msg):
        #handle login

    def __onLogout(self, msg):
        #handle logout

Update: I wasn't clear in my terminology. I now understand Python dictionary lookups to be of complexity O(1) which makes them the perfect candidate. Thanks.


Solution

  • class MsgID(int):
        pass
    
    LOGIN = MsgID(0)
    LOGOUT = MsgID(1)
    HEARTBEAT = MsgID(2)
    ... # add all other message identifier numbers
    
    class MsgType(object):
        def __init__(self, id, data):
            self.id = id
            self.data = data
    
    
    def login_handler(msg):
        ...  # do something here
    
    def logout_handler(msg):
        ...  # do something here
    
    def heartbeat_handler(msg):
        ...  # do something here
    
    
    msg_func = {
        LOGIN  : login_handler,
        LOGOUT : logout_handler,
        HEARTBEAT : heartbeat_handler,
        ...
    }
    
    
    class Handler(object):
        def handleMsg(self, msg):
            try:
                msg_func[msg.id](msg)  # lookup function reference in dict, call function
            except KeyError:
                log_error_mesg('message without a handler function: %d' % msg.id)
    

    It's not strictly needed, but I added a subclass of int for message ID. That way you can check to see if the ID value is really an ID value rather than just some random integer.

    I assume that each message will have an ID value in it, identifying what sort of message it is, plus some data. The msg_func dictionary uses MsgID values as keys, which map to function references.

    You could put all the functions inside a class, but I didn't do that here; they are just functions.