Re: Move dictionary from instance to class level
Anthony Tolle wrote: > To take things one step further, I would recommend using decorators to > allow symbolic association of functions with the message identifiers, > as follows: > [...] That's neat. Thanks. Frank -- http://mail.python.org/mailman/listinfo/python-list
Re: Move dictionary from instance to class level
"Frank Millman" wrote: Apologies for the triple-post. I use google-groups for reading c.l.py, but I know that some people reject messages from there due to the volume of spam, so on the odd occasion when I want to send something I fire up Outlook Express and send it from there. It seems to be misbehaving today. Sorry about that. Frank -- http://mail.python.org/mailman/listinfo/python-list
Re: Move dictionary from instance to class level
Dave Angel wrote: > OK, that makes good sense. And I withdraw any suggestion to use pickling, > since that could be subject to hacking. > > It now appears that the messages are only incidentally GUI events. And > that you would be well advised to make every possible event a separate > message, so that if the server state and the client state get out of > synch, you can readily check and reject such operations. For example, > you'd have a message for pressing the SUBMIT button on a particular form, > but you'd have different message types for other buttons on the same form, > or for SUBMIT on other forms. > I use the same message type for all SUBMITs, but the body of the message contains a unique id for each button. When the server constructs the form, it assigns a unique id to each widget, and includes this id in the form definition it sends to the client. Therefore the server and client can unambiguously reference specific widgets, and there is no real danger of getting out of sync. Frank -- http://mail.python.org/mailman/listinfo/python-list
Re: Move dictionary from instance to class level
Frank Millman wrote: Dave Angel wrote: Frank Millman wrote: That is definitely *not* what I want to do. I want to make the server as generic as possible, so that it can handle any type of client, hopefully even including a browser eventually. Therefore the server has no knowledge of wxPython event types. I have abstracted all the event types I am interested in (the list is fairly stable now). My protocol requires that the client maps a specific gui event type to a message identifier, and the server maps the message identifier to a method that handles the message. Hope that makes sense. Frank Yes, it makes sense. Sorry for heading down that particular dead-end. But the more I think about it, the more likely I think it is that you'll be adding new message types, even if they're just variants of ones already defined. So it might behoove you to have a shared "data structure" that describes the whole message, not just equates a name to an integer. Or consider pickling. I don't know the tradeoffs, but the idea is that an object is constructed at the other end that has all the same data members as the object you had at this end. Perhaps with a flexible enough class definition, you could represent all or at least several of your messages with the same object. I am curious about your topology. You're sending events from the client (which presumably has a mouse and keyboard) to a server. But what does the server do with those? Does it have its own screen, or what? I'll try to explain. I am writing a fairly standard business/accounting application. (I am now adding Business Process Management to it, which is complicating matters, but that is another story.) Most of the gui stuff is basic forms processing - screens with static data, text fields for display and input of data, and buttons for signifying certain actions to be taken. My original attempt had both the gui and the business logic running on the client, with a connection to a database running on a server. It worked, but then I realised it was very insecure - it would be easy to hack the python code, bypass the business logic, and allow any update to the database. So my second attempt took all the business logic out of the client and put it onto the server. To execute a form, the server builds a form definition by creating objects to represent each of the widgets, creates a list of the components with sufficient information for the client to render them , then sends a json'd copy of the list to the client, which interprets it and displays the required form. The client informs the server of each event, and the server handles the event in much the same way as it did before when the business logic was on the client. For example, clicking a button triggers a response which could involve updating the database, displaying another window with additional data, etc, etc. Previously there would have been a method on the client designed to handle the response, and the method would be added to the button constructor so that it would be called when the button was clicked. Now the method is on the server, and is stored as an attribute of the button object on the server. When the user clicks the button, the message is passed up to the server (each widget has its own id, which is part of the message), the server is notified that the button was clicked, and it calls the associated method. There is a lot more to it than that, but hopefully that will give you an idea. If I ever get this to a workable state (it is taking far longer than I anticipated) I will release it as open source, and will then welcome as much feedback as possible. Frank OK, that makes good sense. And I withdraw any suggestion to use pickling, since that could be subject to hacking. It now appears that the messages are only incidentally GUI events. And that you would be well advised to make every possible event a separate message, so that if the server state and the client state get out of synch, you can readily check and reject such operations. For example, you'd have a message for pressing the SUBMIT button on a particular form, but you'd have different message types for other buttons on the same form, or for SUBMIT on other forms. DaveA -- http://mail.python.org/mailman/listinfo/python-list
Re: Move dictionary from instance to class level
To take things one step further, I would recommend using decorators to allow symbolic association of functions with the message identifiers, as follows: == (MESSAGE_ONE ,MESSAGE_TWO ,MESSAGE_THREE ) = xrange(3) class MyClass(object): method_dict = {} # create helper decorator register_method = lambda msg, method_dict=method_dict: lambda function: method_dict.setdefault(msg, function) @register_method(MESSAGE_ONE) def handle_one(self): print 'handling MESSAGE_ONE' @register_method(MESSAGE_TWO) def handle_two(self): print 'handling MESSAGE_TWO' @register_method(MESSAGE_THREE) def handle_three(self): print 'handling MESSAGE_THREE' # no longer need helper decorator del register_method # function to dispatch messages def on_message_received(self, msg): MyClass.method_dict[msg](self) x = MyClass() x.on_message_received(MESSAGE_ONE) x.on_message_received(MESSAGE_TWO) x.on_message_received(MESSAGE_THREE) == Note: the line containing the lambda definition is all one line. -- http://mail.python.org/mailman/listinfo/python-list
RE: Move dictionary from instance to class level
Dave Angel wrote: > > Frank Millman wrote: > > > > That is definitely *not* what I want to do. > > > > I want to make the server as generic as possible, so that > it can handle any > > type of client, hopefully even including a browser > eventually. Therefore the > > server has no knowledge of wxPython event types. > > > > I have abstracted all the event types I am interested in > (the list is fairly > > stable now). My protocol requires that the client maps a > specific gui event > > type to a message identifier, and the server maps the > message identifier to > > a method that handles the message. > > > > Hope that makes sense. > > > > Frank > > > > > > > Yes, it makes sense. Sorry for heading down that particular > dead-end. > But the more I think about it, the more likely I think it is > that you'll > be adding new message types, even if they're just variants of ones > already defined. So it might behoove you to have a shared "data > structure" that describes the whole message, not just equates > a name to > an integer. > > Or consider pickling. I don't know the tradeoffs, but the > idea is that > an object is constructed at the other end that has all the same data > members as the object you had at this end. Perhaps with a flexible > enough class definition, you could represent all or at least > several of > your messages with the same object. > > I am curious about your topology. You're sending events from > the client > (which presumably has a mouse and keyboard) to a server. But > what does > the server do with those? Does it have its own screen, or what? > I'll try to explain. I am writing a fairly standard business/accounting application. (I am now adding Business Process Management to it, which is complicating matters, but that is another story.) Most of the gui stuff is basic forms processing - screens with static data, text fields for display and input of data, and buttons for signifying certain actions to be taken. My original attempt had both the gui and the business logic running on the client, with a connection to a database running on a server. It worked, but then I realised it was very insecure - it would be easy to hack the python code, bypass the business logic, and allow any update to the database. So my second attempt took all the business logic out of the client and put it onto the server. To execute a form, the server builds a form definition by creating objects to represent each of the widgets, creates a list of the components with sufficient information for the client to render them , then sends a json'd copy of the list to the client, which interprets it and displays the required form. The client informs the server of each event, and the server handles the event in much the same way as it did before when the business logic was on the client. For example, clicking a button triggers a response which could involve updating the database, displaying another window with additional data, etc, etc. Previously there would have been a method on the client designed to handle the response, and the method would be added to the button constructor so that it would be called when the button was clicked. Now the method is on the server, and is stored as an attribute of the button object on the server. When the user clicks the button, the message is passed up to the server (each widget has its own id, which is part of the message), the server is notified that the button was clicked, and it calls the associated method. There is a lot more to it than that, but hopefully that will give you an idea. If I ever get this to a workable state (it is taking far longer than I anticipated) I will release it as open source, and will then welcome as much feedback as possible. Frank -- http://mail.python.org/mailman/listinfo/python-list
Re: Move dictionary from instance to class level
Frank Millman wrote: Dave Angel wrote: Show me a sample client event handler, and maybe I can suggest how to encode it. For example in wxPython, events are encoded with an event object. You could have the event send the object's type-string as an event ID. No lookup at all. And in fact, one event handler then might handle several of the events for a given widget, or even for multiple ones. I guess it's not that simple, since you frequently have to pass other information, such as the state of the Ctrl-key, or the mouse position on the screen, which is not directly encoded in the event type. That is definitely *not* what I want to do. I want to make the server as generic as possible, so that it can handle any type of client, hopefully even including a browser eventually. Therefore the server has no knowledge of wxPython event types. I have abstracted all the event types I am interested in (the list is fairly stable now). My protocol requires that the client maps a specific gui event type to a message identifier, and the server maps the message identifier to a method that handles the message. Hope that makes sense. Frank Yes, it makes sense. Sorry for heading down that particular dead-end. But the more I think about it, the more likely I think it is that you'll be adding new message types, even if they're just variants of ones already defined. So it might behoove you to have a shared "data structure" that describes the whole message, not just equates a name to an integer. Or consider pickling. I don't know the tradeoffs, but the idea is that an object is constructed at the other end that has all the same data members as the object you had at this end. Perhaps with a flexible enough class definition, you could represent all or at least several of your messages with the same object. I am curious about your topology. You're sending events from the client (which presumably has a mouse and keyboard) to a server. But what does the server do with those? Does it have its own screen, or what? DaveA -- http://mail.python.org/mailman/listinfo/python-list
RE: Move dictionary from instance to class level
Dave Angel wrote: > > Show me a sample client event handler, and maybe I can suggest how to > encode it. For example in wxPython, events are encoded with > an event > object. You could have the event send the object's type-string as an > event ID. No lookup at all. And in fact, one event handler > then might > handle several of the events for a given widget, or even for multiple > ones. I guess it's not that simple, since you frequently > have to pass > other information, such as the state of the Ctrl-key, or the mouse > position on the screen, which is not directly encoded in the > event type. That is definitely *not* what I want to do. I want to make the server as generic as possible, so that it can handle any type of client, hopefully even including a browser eventually. Therefore the server has no knowledge of wxPython event types. I have abstracted all the event types I am interested in (the list is fairly stable now). My protocol requires that the client maps a specific gui event type to a message identifier, and the server maps the message identifier to a method that handles the message. Hope that makes sense. Frank -- http://mail.python.org/mailman/listinfo/python-list
Re: Move dictionary from instance to class level
Frank Millman wrote: Dave Angel wrote: Any time I see multiple lists like that which have to stay in synch, I think code-smell. I don't think it is that bad, but I agree there is always room for improvement. Why not let the EVT's be passed as strings, and avoid the whole mapping to integers and mapping back detail? And name the methods involved in a way that you can directly translate the string to the method name? There is some merit in this. At present I am writing the server and the client, and copy/paste the list of constants, so they are guaranteed to stay in sync. (Maybe I should import it instead - even more fool-proof [the fool being me, of course]). However, it may happen that I want to open it up to 3rd-party clients in the future, in which case I would have to publish some sort of API. It would make more sense to identify the messages by a meaningful name rather than an integer. And yes, I could then use 'getattr' to retrieve the corresponding method on the server side. I've built such pairs of programs (not in Python), and studied the tradeoffs of various methods of coupling. Cut & Paste is probably the worst way to do it. Manual error is easy to creep in, where one copy is updated, and somebody neglects to update the other. It's especially bad if the item order matters, as it does for enums and for your xlist() example. Shared code works okay (have a module that both ends import). But it assumes both ends are built and ship and install on a consistent basis. Not too hard when it's a single product on a single machine. But if the two ends are on separate machines, especially separated by the Internet, you have to deal with version consistency problems. If there's a time shift as well (file format), then you're stuck at that level. Check the version, and either insist on exact match, or have a way to adapt to whichever end reports the earlier version. Make no mistake, there will be new versions, and you'll have to deal with it. Shared data is about the same, but can sometimes be more flexibly interpreted. It also can have the advantage of being able to have multiple simultaneous versions on the same machine. For the Internet case, picture a server that has to be able to serve several clients, each running different versions. And it's tougher for corruption (accidental or malicious) to do serious damage. I wouldn't want to do an import over the Internet live connection. Best is if the necessary data is passed between the two ends during initialization, and both ends know how to make that data describe the protocol they'll use. That can work as long as there's a notion of a session, and preferably if the session is two-way. In the case of file formats, it means you have this data in the header of the file. Sometimes for bandwidth reasons, you just want to transmit a version string, and not the entire table implied by that string. Just realize the increased risks involved. Probably the easiest way to stay in synch is if each message is self-describing. To me that screams "text" for the id's. It makes the message a bit larger, and you have to decide if it's worth it. The overhead could very well be lost in the noise of packeting, in any tcp/ip protocol. Note that all these have very gray boundaries. And that underneath it all, it's all just data. Barring that, make a single "structure" which lists the event names and method names in matched pairs, and derive whatever lists and dictionaries you actually need from that one structure. And that structure should be shared between client and server code, perhaps as a text file that they both parse. Or as a stream that's passed from one to the other during startup. That way, consistency between them can be regulated (with version string in the file, for example) I'm not sure how that would work. On the client side, I need to respond to a 'button-clicked' event from the gui system by sending an EVT_BUTTON_CLICKED message to the server. In other words it is hard-coded into the client program. I don't know how that would work if I read in a list of message-types at startup. Show me a sample client event handler, and maybe I can suggest how to encode it. For example in wxPython, events are encoded with an event object. You could have the event send the object's type-string as an event ID. No lookup at all. And in fact, one event handler then might handle several of the events for a given widget, or even for multiple ones. I guess it's not that simple, since you frequently have to pass other information, such as the state of the Ctrl-key, or the mouse position on the screen, which is not directly encoded in the event type. DaveA Thanks for the input - it is always good to have some fresh ideas. Frank -- http://mail.python.org/mailman/listinfo/python-list
RE: Move dictionary from instance to class level
Dave Angel wrote: > Any time I see multiple lists like that which have to stay in > synch, I think code-smell. > I don't think it is that bad, but I agree there is always room for improvement. > Why not let the EVT's be passed as strings, and avoid the whole mapping > to integers and mapping back detail? And name the methods involved in a > way that you can directly translate the string to the method name? > There is some merit in this. At present I am writing the server and the client, and copy/paste the list of constants, so they are guaranteed to stay in sync. (Maybe I should import it instead - even more fool-proof [the fool being me, of course]). However, it may happen that I want to open it up to 3rd-party clients in the future, in which case I would have to publish some sort of API. It would make more sense to identify the messages by a meaningful name rather than an integer. And yes, I could then use 'getattr' to retrieve the corresponding method on the server side. > Barring that, make a single "structure" which lists the event > names and > method names in matched pairs, and derive whatever lists and > dictionaries you actually need from that one structure. And that > structure should be shared between client and server code, > perhaps as a > text file that they both parse. Or as a stream that's passed > from one > to the other during startup. That way, consistency between > them can be > regulated (with version string in the file, for example) > I'm not sure how that would work. On the client side, I need to respond to a 'button-clicked' event from the gui system by sending an EVT_BUTTON_CLICKED message to the server. In other words it is hard-coded into the client program. I don't know how that would work if I read in a list of message-types at startup. > DaveA > Thanks for the input - it is always good to have some fresh ideas. Frank -- http://mail.python.org/mailman/listinfo/python-list
Re: Move dictionary from instance to class level
Frank Millman wrote: "MRAB" wrote in message news:mailman.444.1251290454.2854.python-l...@python.org... An alternative is: class MyClass(object): ... def on_message_received(self, msg): ... try: ... getattr(self, "method_%d" % msg)() ... except AttributeError: ... raise Exception("Unknown message") ... def method_0(self): ... print 'in method_0' ... def method_1(self): ... print 'in method_1' ... my_obj = MyClass() my_obj.on_message_received(0) in method_0 my_obj.on_message_received(1) in method_1 my_obj.on_message_received(2) Traceback (most recent call last): File "", line 1, in File "", line 6, in on_message_received Exception: Unknown message I like the idea. Unfortunately my real-world situation is a little more complex than my simple example implied. This is a more typical example - (EVT_GETLOGIN ,EVT_LOGOUT ,EVT_GETMENUOPT ,EVT_GOTFOCUS ,EVT_LOSTFOCUS ,EVT_BUTTONCLICKED ,EVT_CHECKBOX ... ) = xrange(28) method_dict = {} method_dict[EVT_GETLOGIN] = onGetLogin method_dict[EVT_LOGOUT] = onLogout method_dict[EVT_GETMENUOPT] = onGetMenuOpt method_dict[EVT_GOTFOCUS] = onGotFocus method_dict[EVT_LOSTFOCUS] = onLostFocus method_dict[EVT_BUTTONCLICKED] = onButtonClicked method_dict[EVT_CHECKBOX] = onCheckBox You can probably figure out from my method names what I am doing here - the messages are sent by a thin client (wxPython), and processed by a server.I am anticipating some "don't do that" responses, but I like the concept, and so far it is very fast and responsive, so I will pursue it for now. Thanks for the input. Frank Any time I see multiple lists like that which have to stay in synch, I think code-smell. Why not let the EVT's be passed as strings, and avoid the whole mapping to integers and mapping back detail? And name the methods involved in a way that you can directly translate the string to the method name? Barring that, make a single "structure" which lists the event names and method names in matched pairs, and derive whatever lists and dictionaries you actually need from that one structure. And that structure should be shared between client and server code, perhaps as a text file that they both parse. Or as a stream that's passed from one to the other during startup. That way, consistency between them can be regulated (with version string in the file, for example) DaveA -- http://mail.python.org/mailman/listinfo/python-list
Re: Move dictionary from instance to class level
"MRAB" wrote in message news:mailman.444.1251290454.2854.python-l...@python.org... > An alternative is: > > >>> class MyClass(object): > ... def on_message_received(self, msg): > ... try: > ... getattr(self, "method_%d" % msg)() > ... except AttributeError: > ... raise Exception("Unknown message") > ... def method_0(self): > ... print 'in method_0' > ... def method_1(self): > ... print 'in method_1' > ... > >>> my_obj = MyClass() > >>> my_obj.on_message_received(0) > in method_0 > >>> my_obj.on_message_received(1) > in method_1 > >>> my_obj.on_message_received(2) > Traceback (most recent call last): > File "", line 1, in > File "", line 6, in on_message_received > Exception: Unknown message I like the idea. Unfortunately my real-world situation is a little more complex than my simple example implied. This is a more typical example - (EVT_GETLOGIN ,EVT_LOGOUT ,EVT_GETMENUOPT ,EVT_GOTFOCUS ,EVT_LOSTFOCUS ,EVT_BUTTONCLICKED ,EVT_CHECKBOX ... ) = xrange(28) method_dict = {} method_dict[EVT_GETLOGIN] = onGetLogin method_dict[EVT_LOGOUT] = onLogout method_dict[EVT_GETMENUOPT] = onGetMenuOpt method_dict[EVT_GOTFOCUS] = onGotFocus method_dict[EVT_LOSTFOCUS] = onLostFocus method_dict[EVT_BUTTONCLICKED] = onButtonClicked method_dict[EVT_CHECKBOX] = onCheckBox You can probably figure out from my method names what I am doing here - the messages are sent by a thin client (wxPython), and processed by a server.I am anticipating some "don't do that" responses, but I like the concept, and so far it is very fast and responsive, so I will pursue it for now. Thanks for the input. Frank -- http://mail.python.org/mailman/listinfo/python-list
Re: Move dictionary from instance to class level
Frank Millman wrote: On Aug 26, 10:54 am, Chris Rebert wrote: On Wed, Aug 26, 2009 at 1:22 AM, Frank Millman wrote: A class MyClass(object): def on_message_received(self, msg): self.method_dict[msg](self) def method_0(self): print 'in method_0' def method_1(self): print 'in method_1' method_dict method_dict = {0: method_0, 1: method_1} #note this comes *after* the methods in question have been defined Thanks, Chris. This is much better. Is there some reason you aren't using a list instead of a dict? e.g. method_dict = [method_0, method_1, method_2, etc] For that matter, why are you associating methods with integers in the first place? I actually use constants to define my messages, like this - (MESSAGE_ONE ,MESSAGE_TWO ,MESSAGE_THREE ) = xrange(3) I can then refer to the messages by their description, but internally it uses integers. An alternative is: >>> class MyClass(object): ... def on_message_received(self, msg): ... try: ... getattr(self, "method_%d" % msg)() ... except AttributeError: ... raise Exception("Unknown message") ... def method_0(self): ... print 'in method_0' ... def method_1(self): ... print 'in method_1' ... >>> my_obj = MyClass() >>> my_obj.on_message_received(0) in method_0 >>> my_obj.on_message_received(1) in method_1 >>> my_obj.on_message_received(2) Traceback (most recent call last): File "", line 1, in File "", line 6, in on_message_received Exception: Unknown message >>> -- http://mail.python.org/mailman/listinfo/python-list
Re: Move dictionary from instance to class level
On Aug 26, 10:54 am, Chris Rebert wrote: > On Wed, Aug 26, 2009 at 1:22 AM, Frank Millman wrote: > > A > > class MyClass(object): > def on_message_received(self, msg): > self.method_dict[msg](self) > > def method_0(self): > print 'in method_0' > > def method_1(self): > print 'in method_1' > method_dict > > method_dict = {0: method_0, 1: method_1} > #note this comes *after* the methods in question have been defined > Thanks, Chris. This is much better. > Is there some reason you aren't using a list instead of a dict? > e.g. method_dict = [method_0, method_1, method_2, etc] > > For that matter, why are you associating methods with integers in the > first place? > I actually use constants to define my messages, like this - (MESSAGE_ONE ,MESSAGE_TWO ,MESSAGE_THREE ) = xrange(3) I can then refer to the messages by their description, but internally it uses integers. Frank -- http://mail.python.org/mailman/listinfo/python-list
Re: Move dictionary from instance to class level
On Aug 26, 10:54 am, Chris Rebert wrote: > On Wed, Aug 26, 2009 at 1:22 AM, Frank Millman wrote: > > A > > class MyClass(object): > def on_message_received(self, msg): > self.method_dict[msg](self) > > def method_0(self): > print 'in method_0' > > def method_1(self): > print 'in method_1' > method_dict > > method_dict = {0: method_0, 1: method_1} > #note this comes *after* the methods in question have been defined > Thanks, Chris. This is much better. > Is there some reason you aren't using a list instead of a dict? > e.g. method_dict = [method_0, method_1, method_2, etc] > > For that matter, why are you associating methods with integers in the > first place? > I actually use constants to define my messages, like this - (MESSAGE_ONE ,MESSAGE_TWO ,MESSAGE_THREE ) = xrange(3) I can then refer to the messages by their description, but internally it uses integers. Frank -- http://mail.python.org/mailman/listinfo/python-list
Re: Move dictionary from instance to class level
On Aug 26, 10:54 am, Chris Rebert wrote: > On Wed, Aug 26, 2009 at 1:22 AM, Frank Millman wrote: > > A > > class MyClass(object): > def on_message_received(self, msg): > self.method_dict[msg](self) > > def method_0(self): > print 'in method_0' > > def method_1(self): > print 'in method_1' > method_dict > > method_dict = {0: method_0, 1: method_1} > #note this comes *after* the methods in question have been defined > Thanks, Chris. This is much better. > Is there some reason you aren't using a list instead of a dict? > e.g. method_dict = [method_0, method_1, method_2, etc] > > For that matter, why are you associating methods with integers in the > first place? > I actually use constants to define my messages, like this - (MESSAGE_ONE ,MESSAGE_TWO ,MESSAGE_THREE ) = xrange(3) I can then refer to the messages by their description, but internally it uses integers. Frank -- http://mail.python.org/mailman/listinfo/python-list
Re: Move dictionary from instance to class level
On Wed, Aug 26, 2009 at 1:22 AM, Frank Millman wrote: > Hi all > > I have a class that uses a dictionary to map message numbers to methods. > > Here is a simple example - > > class MyClass(object): > def __init__(self): > self.method_dict = {} > self.method_dict[0] = self.method_0 > self.method_dict[1] = self.method_1 > > def on_message_received(self, msg): > self.method_dict[msg]() > > def method_0(self): > print 'in method_0' > > def method_1(self): > print 'in method_1' > > I have quite a few methods, so the dictionary is growing - up to 28 methods > so far. To avoid > having to recreate the dictionary every time I create an instance of the > class, I tried to move it > up to the class level. Unfortunately it does not work. This is what I > tried - > > class MyClass(object): > method_dict = {} > method_dict[0] = method_0 # this gives an error > method_dict[1] = method_1 > > def on_message_received(self, msg): > self.method_dict[msg]() > > def method_0(self): > print 'in method_0' > > def method_1(self): > print 'in method_1' > > As written above, I get the following error - > NameError: name 'method_0' is not defined > > If I try self.method_0, I get 'self' is not defined. Right, because you're in the *class* body; there's no "current instance" to be "self"; in fact, there's not even any class for there to be instances of yet. > If I try __class__.method_0, I get '__class__' is not defined. Right, because the class isn't created until its body has finished executing > If I try MyClass.method_0, I get 'MyClass' is not defined. See previous note. The class name can't be bound to anything until the class itself has been created. > Is there any variation on this theme that will work? > > # > > Ok, I found a variation that seems to work. > > Is this the preferred way, or is there a better alternative? A class MyClass(object): def on_message_received(self, msg): self.method_dict[msg](self) def method_0(self): print 'in method_0' def method_1(self): print 'in method_1' method_dict method_dict = {0: method_0, 1: method_1} #note this comes *after* the methods in question have been defined Is there some reason you aren't using a list instead of a dict? e.g. method_dict = [method_0, method_1, method_2, etc] For that matter, why are you associating methods with integers in the first place? Cheers, Chris -- http://blog.rebertia.com -- http://mail.python.org/mailman/listinfo/python-list
Move dictionary from instance to class level
Hi all I have a class that uses a dictionary to map message numbers to methods. Here is a simple example - class MyClass(object): def __init__(self): self.method_dict = {} self.method_dict[0] = self.method_0 self.method_dict[1] = self.method_1 def on_message_received(self, msg): self.method_dict[msg]() def method_0(self): print 'in method_0' def method_1(self): print 'in method_1' I have quite a few methods, so the dictionary is growing - up to 28 methods so far. To avoid having to recreate the dictionary every time I create an instance of the class, I tried to move it up to the class level. Unfortunately it does not work. This is what I tried - class MyClass(object): method_dict = {} method_dict[0] = method_0 # this gives an error method_dict[1] = method_1 def on_message_received(self, msg): self.method_dict[msg]() def method_0(self): print 'in method_0' def method_1(self): print 'in method_1' As written above, I get the following error - NameError: name 'method_0' is not defined If I try self.method_0, I get 'self' is not defined. If I try __class__.method_0, I get '__class__' is not defined. If I try MyClass.method_0, I get 'MyClass' is not defined. Is there any variation on this theme that will work? # Ok, I found a variation that seems to work. Is this the preferred way, or is there a better alternative? class MyClass(object): def on_message_received(self, msg): #self.method_dict[msg]() # had to change this to get it to work self.method_dict[msg](self) def method_0(self): print 'in method_0' def method_1(self): print 'in method_1' MyClass.method_dict = {} MyClass.method_dict[0] = MyClass.method_0 MyClass.method_dict[1] = MyClass.method_1 As you can see, I had to add 'self' to the method arguments when calling the method. Any comments? Thanks Frank Millman -- http://mail.python.org/mailman/listinfo/python-list