can i define a new method at runtime?

Discussion in 'Python' started by Raoul, Jun 18, 2004.

  1. Raoul

    Raoul Guest

    I have a GUI application where I want to assign validation methods to
    controls.

    If my control myTextBox has a change() event for on change and I want
    to make it verify the input is an integer I could do...

    def myTextBox.change():
    verifyInteger(myTextBox.Value)

    def verifyInteger(x):
    try:
    string.atoi(x.value)
    except ValueError :
    message(x," needs to be an integer")
    x.setFocus()

    but i have literally hundreds of these things to do....

    I'd like to be able to say somethign like

    myTextBox.change = lambda x : verifyInteger(x)

    so when i initialize my form i'd like to run through a list that looks
    like

    [["controlName1","verifyInteger"],["controlName2,"verifyFloat"],["controlName3
    "verifyInteger"]

    but i can't seem to make this work.

    I've tried to use exec("def foo = lambda x: do something....")

    but that doesn't seem to work....

    Got any ideas ???
    Raoul, Jun 18, 2004
    #1
    1. Advertising

  2. Raoul wrote:

    > If my control myTextBox has a change() event for on change and I want
    > to make it verify the input is an integer I could do...
    >
    > def myTextBox.change():
    > verifyInteger(myTextBox.Value)
    >
    > def verifyInteger(x):
    > try:
    > string.atoi(x.value)
    > except ValueError :
    > message(x," needs to be an integer")
    > x.setFocus()
    >
    > but i have literally hundreds of these things to do....
    >
    > I'd like to be able to say somethign like
    >
    > myTextBox.change = lambda x : verifyInteger(x)
    >
    > so when i initialize my form i'd like to run through a list that looks
    > like
    >
    > [["controlName1","verifyInteger"],["controlName2,"verifyFloat"],["controlName3
    > "verifyInteger"]


    I'm not a guru, so expect this solution to be bloated ;)

    For example, (ab)use a class to build a unit with all the verify-functions:

    class Verify(object):
    def verify_integer(x): [...]
    def verify_float(x): [...]

    # Then, iterate over the list:

    for pair in list: # list being your example above
    control = getattr(__main__, pair[0])
    control.changed = eval("lambda self: Verify." + pair[1] + "(self.Value)")
    # for this line there MUST be a solution without eval but I don't see it
    at the moment

    BTW, you should use tuples if the information about the handling
    functions is static.

    regards, Reinhold

    --
    Wenn eine Linuxdistribution so wenig brauchbare Software wie Windows
    mitbrächte, wäre das bedauerlich. Was bei Windows der Umfang eines
    "kompletten Betriebssystems" ist, nennt man bei Linux eine Rescuedisk.
    -- David Kastrup in de.comp.os.unix.linux.misc
    Reinhold Birkenfeld, Jun 18, 2004
    #2
    1. Advertising

  3. Raoul

    Ville Vainio Guest

    >>>>> "Raoul" == Raoul <> writes:

    Raoul> I have a GUI application where I want to assign validation
    Raoul> methods to controls.

    Raoul> If my control myTextBox has a change() event for on change
    Raoul> and I want to make it verify the input is an integer I
    Raoul> could do...

    If there is a change method, I assume you need to implement the class
    yourself. Why not just subclass the root TextBox class and create a
    IntegerTextBox class that has verifyInteger in the change method? Then
    you just choose at instantiation time that this particular textbox
    needs an integer...

    --
    Ville Vainio http://tinyurl.com/2prnb
    Ville Vainio, Jun 19, 2004
    #3
  4. Raoul

    Larry Bates Guest

    You are close. Try something like

    def verifyInteger(x):
    try:
    string.atoi(x.value)
    except ValueError :
    message(x," needs to be an integer")
    x.setFocus()

    In a dictionary put keys (controlNames) and
    pointers to what function (or method) to call
    for that controlName.

    verifiers={'controlName1': verifyInteger,
    'controlName2': verifyFloat,
    ...
    'controlNameN': veryfySomething}


    In your program call the function from the
    dictionary as follows:

    verifiers['controlName1'](x)
    verifiers['controlName2'](x)
    ....

    This works because the result of the getting
    verifiers[controlName] is a pointer to a
    function instead of a value. This pointer
    has a call method, so you can just put the
    arguments after it.

    HTH,
    Larry Bates
    Syscon, Inc.

    "Raoul" <> wrote in message
    news:...
    > I have a GUI application where I want to assign validation methods to
    > controls.
    >
    > If my control myTextBox has a change() event for on change and I want
    > to make it verify the input is an integer I could do...
    >
    > def myTextBox.change():
    > verifyInteger(myTextBox.Value)
    >
    > def verifyInteger(x):
    > try:
    > string.atoi(x.value)
    > except ValueError :
    > message(x," needs to be an integer")
    > x.setFocus()
    >
    > but i have literally hundreds of these things to do....
    >
    > I'd like to be able to say somethign like
    >
    > myTextBox.change = lambda x : verifyInteger(x)
    >
    > so when i initialize my form i'd like to run through a list that looks
    > like
    >
    >

    [["controlName1","verifyInteger"],["controlName2,"verifyFloat"],["controlNam
    e3
    > "verifyInteger"]
    >
    > but i can't seem to make this work.
    >
    > I've tried to use exec("def foo = lambda x: do something....")
    >
    > but that doesn't seem to work....
    >
    > Got any ideas ???
    Larry Bates, Jun 20, 2004
    #4
  5. Raoul

    Hung Jung Lu Guest

    (Raoul) wrote:
    >
    > but i have literally hundreds of these things to do....
    >
    > I'd like to be able to say somethign like
    >
    > myTextBox.change = lambda x : verifyInteger(x)
    >
    > so when i initialize my form i'd like to run through a list that looks
    > like
    >
    > [["controlName1","verifyInteger"],["controlName2,"verifyFloat"],["controlName3
    > "verifyInteger"]


    def change_Integer(self):
    try:
    string.atoi(self.value)
    except ValueError:
    message(...)
    self.setFocous()
    def change_Currrency(self):
    ...

    dict = {"box1": "Integer", "box2": "Currency"}

    import new
    for (box_name, box_type) in dict.iteritems():
    function_name = 'change_%s' % box_type
    f = eval(function_name)
    box = getattr(myFrame, box_name)
    box.change = new.instancemethod(f, box, box.__class__)

    replace eval() by globals() if safety is a concern, or replace by
    getattr(...) if functions are defined in modules or classes. (.im_func
    maybe needed, anyway, you'll figure out the specifics on your own.)

    Hung Jung
    Hung Jung Lu, Jun 20, 2004
    #5
  6. Raoul

    Hung Jung Lu Guest

    Ville Vainio <> wrote:
    > If there is a change method, I assume you need to implement the class
    > yourself. Why not just subclass the root TextBox class and create a
    > IntegerTextBox class that has verifyInteger in the change method? Then
    > you just choose at instantiation time that this particular textbox
    > needs an integer...


    This is OK if there are only a few types of boxes. But entry data
    types are features, and they tend to grow and become complicated, even
    if Regex (regular expression) patterns were used. Besides, the
    verification logic is a conceptual unit on its own right, so according
    to the AOP (aspect-oriented programming) philosophy, it's best to
    group the verification methods together in some "aspect class". There
    may be new dimensions to the problem that one may not have foreseen at
    the time of design. For instance, localization (currency, dates, usage
    of commas and periods, ZIP codes, etc.) Having verification code in
    its own hierarchy allows you to make changes more easily and take
    advantage of class inheritance for code re-use. Once you have the
    verification logic done, you hook it to the widget objects somehow. In
    Python, this usually involves some form of metaprogramming. There are
    too many ways to do it, and you'll probably not find two people doing
    it the same way. Some tools in the arsenal are: using
    functions/methods as first class objects and assign them or tweak them
    to your heart's content, using the "new" module, using code objects
    and "exec" statements, tweaking an existing object's __class__
    attribute, implementing/overriding the __getattr__() method in
    classes, metaclasses, etc. etc.

    regards,

    Hung Jung
    Hung Jung Lu, Jun 20, 2004
    #6
  7. Raoul

    Jeff Epler Guest

    Something like the untested code below will work, without the need to
    "exec" anything.

    def verifyInteger(x): ...
    def verifyFloat(x): ...
    verifiers = {"ControlName1": verifyInteger, "ControlName2": verifyFloat, ....}

    class MyTextBox(TextBox):
    def __init__(self, controlname, ...):
    self.verifyfunc = verifiers[self.controlname]
    TextBox.__init__(self, ...)
    ...
    def change(self):
    self.verifyfunc(self.value)

    Jeff

    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.2.4 (GNU/Linux)

    iD8DBQFA1szcJd01MZaTXX0RAizxAJ4lzaIFRv5xeS0+YlD3rKevATT4kACgjbwn
    izanXr8+GfuUL9sRfERyi2w=
    =12C3
    -----END PGP SIGNATURE-----
    Jeff Epler, Jun 21, 2004
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. theotyflos
    Replies:
    3
    Views:
    466
    Thomas Matthews
    Feb 19, 2004
  2. robin liu
    Replies:
    3
    Views:
    821
    Robin Liu
    Apr 21, 2006
  3. Benny
    Replies:
    3
    Views:
    107
    Mauricio Fernández
    Jul 13, 2004
  4. Brian Takita

    #define _ and #define __

    Brian Takita, Jan 23, 2006, in forum: Ruby
    Replies:
    0
    Views:
    460
    Brian Takita
    Jan 23, 2006
  5. John J. Franey
    Replies:
    3
    Views:
    132
    George
    Jun 15, 2007
Loading...

Share This Page