How to code dynamically created methods?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • kj

    #1

    How to code dynamically created methods?



    I've tried a bazillion ways to code dynamically generated methods,
    to no avail.

    The following snippet is a very simplified (and artificial) demo
    of the problem I'm running into, featuring my latest attempt at
    this. The idea here is to use __getattr__ to trap any attempt to
    invoke a nonexistent method, have it return a generic handler called
    _auto which creates the new method dynamically, invokes it, and
    "installs" it in the class, so that subsequent calls to the same
    method go directly to the newly created method, instead of to
    __getattr__. It is this last step, the "installati on" of the new
    method, that is giving me problems.


    class A( object ):
    def __getattr__( self, name ):
    self._auto_name = name
    return self._auto

    def hello( self, name ):
    print "hi! my name is %s" % name

    def _auto( self, *args ):
    name = self._auto_name
    def m( self, *args ): self.hello( name )
    m( self, *args )

    m = classmethod( m )
    setattr( A, name, m )

    x = A()
    x.foo() # ok
    x.foo() # bombs

    >>reload(test ) hi! my name is foo Traceback (most recent call
    last):
    File "<stdin>", line 1, in ? File "test.py", line 19, in ?
    x.foo() File "test.py", line 12, in m
    self.hello( name ) TypeError: unbound method hello() must be
    called with A instance as first argument (got str instance instead)
    >>>
    I'm sure that the problem is with my naive attempt to add a method
    to class A dynamically (in the last two lines of the definition of
    _auto). What's the right way to do this?

    Thanks!

    kj

    --
    NOTE: In my address everything before the first period is backwards;
    and the last period, and everything after it, should be discarded.
  • kj

    #2
    Re: How to code dynamically created methods?


    Nevermind, I found the problem...

    Thanks,

    kj

    In <f5bb99$2jr$1@r eader2.panix.co mkj <socyl@987jk.co m.invalidwrites :


    >I've tried a bazillion ways to code dynamically generated methods,
    >to no avail.
    >The following snippet is a very simplified (and artificial) demo
    >of the problem I'm running into, featuring my latest attempt at
    >this. The idea here is to use __getattr__ to trap any attempt to
    >invoke a nonexistent method, have it return a generic handler called
    >_auto which creates the new method dynamically, invokes it, and
    >"installs" it in the class, so that subsequent calls to the same
    >method go directly to the newly created method, instead of to
    >__getattr__. It is this last step, the "installati on" of the new
    >method, that is giving me problems.
    >class A( object ):
    def __getattr__( self, name ):
    self._auto_name = name
    return self._auto
    def hello( self, name ):
    print "hi! my name is %s" % name
    >
    def _auto( self, *args ):
    name = self._auto_name
    def m( self, *args ): self.hello( name )
    m( self, *args )
    m = classmethod( m )
    setattr( A, name, m )
    >x = A()
    >x.foo() # ok
    >x.foo() # bombs
    >>>reload(tes t) hi! my name is foo Traceback (most recent call
    >last):
    File "<stdin>", line 1, in ? File "test.py", line 19, in ?
    x.foo() File "test.py", line 12, in m
    self.hello( name ) TypeError: unbound method hello() must be
    >called with A instance as first argument (got str instance instead)
    >>>>
    >I'm sure that the problem is with my naive attempt to add a method
    >to class A dynamically (in the last two lines of the definition of
    >_auto). What's the right way to do this?
    >Thanks!
    >kj
    >--
    >NOTE: In my address everything before the first period is backwards;
    >and the last period, and everything after it, should be discarded.
    --
    NOTE: In my address everything before the first period is backwards;
    and the last period, and everything after it, should be discarded.

    Comment

    • Ben Finney

      #3
      Re: How to code dynamically created methods?

      kj <socyl@987jk.co m.invalidwrites :
      Nevermind, I found the problem...
      Please share the solution with the list, if you would.

      --
      \ "I must say that I find television very educational. The minute |
      `\ somebody turns it on, I go to the library and read a book." -- |
      _o__) Groucho Marx |
      Ben Finney

      Comment

      • Jay Loden

        #4
        Re: How to code dynamically created methods?


        kj wrote:
        >
        I've tried a bazillion ways to code dynamically generated methods,
        to no avail.
        >
        The following snippet is a very simplified (and artificial) demo
        of the problem I'm running into, featuring my latest attempt at
        this. The idea here is to use __getattr__ to trap any attempt to
        invoke a nonexistent method, have it return a generic handler called
        _auto which creates the new method dynamically, invokes it, and
        "installs" it in the class, so that subsequent calls to the same
        method go directly to the newly created method, instead of to
        __getattr__. It is this last step, the "installati on" of the new
        method, that is giving me problems.
        >
        >
        class A( object ):
        def __getattr__( self, name ):
        self._auto_name = name
        return self._auto
        >
        def hello( self, name ):
        print "hi! my name is %s" % name
        >
        def _auto( self, *args ):
        name = self._auto_name
        def m( self, *args ): self.hello( name )
        m( self, *args )
        >
        m = classmethod( m )
        setattr( A, name, m )
        >
        x = A()
        x.foo() # ok
        x.foo() # bombs
        >
        I tried to do the same exact thing recently and got my answer from the mailing list. Here's the test code I got working using the help from the list:

        #!/usr/bin/python

        import functools

        class TestClass:
        def __init__(self):
        pass

        def __getattr__(sel f, name):
        try:
        return getattr(self.__ class__, name)
        except AttributeError:
        return functools.parti al(self.foo, name)

        def foo(self, name, **args):
        print name
        for i in args:
        print " %s=%s" % (i, args[i])

        def bar(self):
        print "bar()"

        test = TestClass()
        test.someMethod ()
        test.anotherMet hod()
        test.someMethod ()
        test.bar()

        Hope that helps,

        -Jay

        Comment

        Working...