Adding method at runtime - problem with self

Discussion in 'Python' started by marek.rocki@wp.pl, Mar 5, 2006.

  1. Guest

    First of all, please don't flame me immediately. I did browse archives
    and didn't see any solution to my problem.

    Assume I want to add a method to an object at runtime. Yes, to an
    object, not a class - because changing a class would have global
    effects and I want to alter a particular object only. The following
    approach fails:

    class kla:
    x = 1

    def foo(self):
    print self.x

    k = kla()
    k.foo = foo
    k.foo()

    I know where the problem is. The method shouldn't have 'self'
    parameter. But how do I access object's attributes without it?

    Best regards,

    Marek
     
    , Mar 5, 2006
    #1
    1. Advertising

  2. On 5 Mar 2006 14:13:21 -0800, declaimed the following
    in comp.lang.python:

    >
    > def foo(self):
    > print self.x
    >
    > k = kla()
    > k.foo = foo
    > k.foo()
    >
    > I know where the problem is. The method shouldn't have 'self'
    > parameter. But how do I access object's attributes without it?
    >

    No... the "method" should have something for "self"... The problem
    is that

    k.foo = foo

    doesn't set up the "magic" to make foo behave like a "method"... That
    is:
    k.foo()
    is not being translated into
    foo(k)

    If you explicitly pass the object "k.foo(k)", it works.


    This seems to have worked:


    import new

    class kla(object):
    def __init__(self, dummy):
    self.x = dummy


    def foo(self):
    print self.x


    k = kla(98)
    j = kla(33)

    k.foo = new.instancemethod(foo, k, kla)

    k.foo()
    j.foo()

    E:\UserData\Dennis Lee Bieber\My Documents\Python Progs>python
    script1.py
    98
    Traceback (most recent call last):
    File "script1.py", line 18, in ?
    j.foo()
    AttributeError: 'kla' object has no attribute 'foo'

    E:\UserData\Dennis Lee Bieber\My Documents\Python Progs>



    --
    > ============================================================== <
    > | Wulfraed Dennis Lee Bieber KD6MOG <
    > | Bestiaria Support Staff <
    > ============================================================== <
    > Home Page: <http://www.dm.net/~wulfraed/> <
    > Overflow Page: <http://wlfraed.home.netcom.com/> <
     
    Dennis Lee Bieber, Mar 5, 2006
    #2
    1. Advertising

  3. wrote:
    > First of all, please don't flame me immediately. I did browse archives
    > and didn't see any solution to my problem.
    >
    > Assume I want to add a method to an object at runtime. Yes, to an
    > object, not a class - because changing a class would have global
    > effects and I want to alter a particular object only. The following
    > approach fails:
    >
    > class kla:
    > x = 1
    >
    > def foo(self):
    > print self.x
    >
    > k = kla()
    > k.foo = foo
    > k.foo()
    >
    > I know where the problem is. The method shouldn't have 'self'
    > parameter. But how do I access object's attributes without it?
    >
    > Best regards,
    >
    > Marek
    >


    k.foo(k)
    would work
     
    =?ISO-8859-1?Q?Sch=FCle_Daniel?=, Mar 6, 2006
    #3
  4. a écrit :
    > First of all, please don't flame me immediately.


    Granted - we'll do it later then !-)

    > I did browse archives
    > and didn't see any solution to my problem.
    >
    > Assume I want to add a method to an object at runtime. Yes, to an
    > object, not a class - because changing a class would have global
    > effects and I want to alter a particular object only. The following
    > approach fails:
    >
    > class kla:
    > x = 1
    >
    > def foo(self):
    > print self.x
    >
    > k = kla()
    > k.foo = foo
    > k.foo()
    >
    > I know where the problem is. The method shouldn't have 'self'
    > parameter.


    Yes it should - else :

    > But how do I access object's attributes without it?


    Hey, how's Python itself doing ?-)

    The problem with your code is that foo is a function object, not a
    method object. So you need to turn it into a method object - which is
    (overly simplification ahead) an object that bind a function object to
    an instance and takes care of passing the instance as first param to
    that function (hint: google for 'descriptor').

    Hopefully, function objects provide a method that allow to bind them to
    instances :

    >>> class Toto(object):

    .... def __init__(self, name): self.name = name
    ....
    >>> t1, t2 = Toto('t1'), Toto('t2')
    >>> def fun(self):

    .... print self.name
    >>> t1.fun = fun.__get__(t1)
    >>> t1.fun()

    t1

    FWIW, you would have the same result (which much less pain) by simply
    passing the instance to the function !-) (there's nothing special about
    the word 'self')

    If what you want to do is to provide a specific implementation for a
    given method on a per-instance base, you can do it much more explicitely:

    class MyObject(object):
    def __init__(self, name, custom_do_this=None):
    self.name = name
    self._custom_do_this = custom_do_this

    def _do_this_default(self):
    return "default do_this implementation for %s" % self.name

    def do_this(self):
    if callable(self._custom_do_this):
    return self._custom_do_this(self)
    else:
    return self._do_this_default()

    def custom_do_this(obj):
    return "custom do_this implementation for %s" % obj.name

    myobj = MyObject('myobj')
    print myobj.do_this()
    myobj._custom_do_this = custom_do_this
    print myobj.do_this()

    Agreed, this is not exactly the same thing as *adding* a method, but
    it's (IMHO) somewhat cleaner wrt/ encapsulation and LSP. (Note that you
    can make the default implementation a no-op - the point here is that the
    client code shouldn't have to worry about MyObject's instances having or
    not having a custom implementation for do_this).

    My 2 cents...
     
    Bruno Desthuilliers, Mar 6, 2006
    #4
  5. Guest

    Thank you all for your responses. That's exactly what I needed to know
    - how to bind a function to an object so that it would comply with
    standard calling syntax.

    This is largely a theoretical issue; I just wanted to improve my
    understanding of Python's OOP model. Using such features in real life
    code would probably be classified either as excessive magic or bad
    design. Oh well, at least now I can be an informed participant of
    language holy wars :)

    Marek
     
    , Mar 6, 2006
    #5
  6. wrote:
    > Thank you all for your responses. That's exactly what I needed to know
    > - how to bind a function to an object so that it would comply with
    > standard calling syntax.
    >
    > This is largely a theoretical issue; I just wanted to improve my
    > understanding of Python's OOP model. Using such features in real life
    > code would probably be classified either as excessive magic or bad
    > design.


    or as a dirty-but-pragmatic workaround - just like accessing
    implementation attributes. These are things that one should IMHO better
    avoid if possible, but sometimes a simple hack is better than no
    practical solution at all.

    > Oh well, at least now I can be an informed participant of
    > language holy wars :)


    Welcome on board !-)


    --
    bruno desthuilliers
    python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
    p in ''.split('@')])"
     
    bruno at modulix, Mar 6, 2006
    #6
    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. Ralf W. Grosse-Kunstleve
    Replies:
    16
    Views:
    620
    Lonnie Princehouse
    Jul 11, 2005
  2. Ralf W. Grosse-Kunstleve
    Replies:
    18
    Views:
    620
    Bengt Richter
    Jul 11, 2005
  3. Ralf W. Grosse-Kunstleve
    Replies:
    2
    Views:
    427
    Dan Sommers
    Jul 12, 2005
  4. falcon
    Replies:
    0
    Views:
    401
    falcon
    Jul 31, 2005
  5. Bart Kastermans
    Replies:
    6
    Views:
    423
    Bart Kastermans
    Jul 13, 2008
Loading...

Share This Page