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.

share|improve this question
5  
1. Arrays (I guess you mean tuples or lists) can hold functions. 2. Use a dict. – David Heffernan Jun 13 '12 at 19:27
@DavidHeffernan is exactly right on both points. Python arrays can hold function references, and you should use a dict to solve this problem. – steveha Jun 13 '12 at 19:28
@DavidHeffernan I think you should give that as an answer. – Lattyware Jun 13 '12 at 19:29
@Lattyware You know far more about Python than I do and I'm sure you could write such an answer far better than me. – David Heffernan Jun 13 '12 at 19:31
2  
For reference, you should never omit a detail as key as O(1) access from a question! – David Heffernan Jun 13 '12 at 19:57
show 5 more comments
feedback

1 Answer

up vote 2 down vote accepted
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.

share|improve this answer
Thanks steveha, I appreciate the response however I am specifically trying to work out how store functions in a container which can be indexed into with an integer value. – Graeme Jun 13 '12 at 19:48
Why do you want to do this? What problem are you trying to solve by doing this? Note that you can always build a list of function references, and also build a dict with the same function references, so what you ask for is easily possible. But I don't see the point. – steveha Jun 13 '12 at 19:55
Oh, you were worried about access speed. A dict() is very fast in Python; a dict is a good solution almost anytime you want some sort of sparse data structure. – steveha Jun 13 '12 at 19:57
feedback

Your Answer

 
or
required, but never shown
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.