Adding method to a class on the fly

John Henry john106henry at hotmail.com
Sat Jun 23 15:31:39 EDT 2007


On Jun 23, 10:56 am, Steven D'Aprano
<s... at REMOVE.THIS.cybersource.com.au> wrote:
> On Sat, 23 Jun 2007 09:06:36 -0700, John Henry wrote:
>
> >> > But then how do I create the on_Button1_mouseClick function?
>
> >> That depends on what it is supposed to do, but in general you want a
> >> factory function -- a function that returns functions. Here's a simple
> >> example:
>
> > <snip>
>
> > Steven,
>
> > May be I didn't explain it clearly: the PythonCard package expects to
> > see a function by the name of on_Button1_mouseClick.  I don't do
> > anything to register the callback function.  The package assumes that
> > there is a function by that name whenever I create a button named
> > Button1.  So, if I don't use exec, how can I create a function by that
> > exact name?
>
> def mouseclick_factory(name):
>     def function(self, event):
>         print "You clicked '%s'." % name
>     function.name = "on_%s_mouseClick" % name
>     return function
>
> class Parrot:
>     def __init__(self, name):
>         function = mouseclick_factory(name) # as before
>         method = new.instancemethod(function, self, self.__class__)
>         setattr(self, function.name, method)
>
> And here it is in action:
>
> >>> p = Parrot("Button1")
> >>> p.on_Button1_mouseClick("event")
>
> You clicked 'Button1'.
>
> --
> Steven.


Wouldn't it be nice if it works right away?  :=)

I tried the above method and this is what I have:

#!/usr/bin/python

"""
__version__ = "$Revision: 1.6 $"
__date__ = "$Date: 2004/08/17 19:46:06 $"
"""

import new

from PythonCard import model

rsrc = {'application':{'type':'Application',
          'name':'Minimal',
    'backgrounds': [
    {'type':'Background',
          'name':'bgMin',
          'title':'Minimal PythonCard Application',
          'size':(200, 300),
         'components': [

] # end components
} # end background
] # end backgrounds
} }

def mouseclick_factory(parent, name):
    id_num=int(name[-1:])
    parent.components[name] = {'type':'Button',
                                 'name':name,
                                 'label':name,
                                 'position':(5, 5+id_num*30),
                                 'text':name}
    def function(self, event):
        print "You clicked '%s'." % name
    function.name = "on_%s_mouseClick" % name
    return function

class Minimal(model.Background):
    def on_initialize(self, event):
        self.components['field1'] =
{'type':'TextField','name':'field1','position':(5, 5),'size':(150,
-1),'text':'Hello PythonCard'}
        name = "Button1"
        function = mouseclick_factory(self, name) # as before
        method = new.instancemethod(function, self, self.__class__)
        setattr(self, function.name, method)

if __name__ == '__main__':
    app = model.Application(Minimal, None, rsrc)
    app.MainLoop()

When I click on the button, nothing happens.  However, if I call the
function directly (like right after the setattr line:

        self.on_Button1_mouseClick(event)

it works fine but PythonCard isn't calling this function when I
clicked on the button.




More information about the Python-list mailing list