Tags: class, def, function, method, object, obvious, programming, python, run-time, triedthe, workclass

replace a method in class: how?

On Programmer » Python

10,229 words with 9 Comments; publish: Wed, 07 May 2008 19:10:00 GMT; (20074.22, « »)

Hello,

I want to replace a method in a class during run-time with another function.

I tried

the obvious, but it didn't work:

class This(object):

def update(self,val):

print val

def another_update(obj,val):

print "another",val

t=This()

t.update(5)

t.update=another_update

t.update(5) # this one doesn't work, gives

# TypeError: another_update() takes exactly 2 arguments (1 given)

clearly it isn't seeing it as a method, just an attribute which happens to b

e a

function. Is there a preferred way to do this?

thanks,

Brian Blais

--

bblais.python.todaysummary.com.bryant.edu

http://web.bryant.edu/~bblais

All Comments

Leave a comment...

  • 9 Comments
    • On 27/06/2006 9:14 AM, Brian Blais wrote:

      > Hello,

      > I want to replace a method in a class during run-time with another

      > function. I tried the obvious, but it didn't work:

      > class This(object):

      > def update(self,val):

      > print val

      > def another_update(obj,val):

      > print "another",val

      > t=This()

      > t.update(5)

      > t.update=another_update

      > t.update(5) # this one doesn't work, gives

      > # TypeError: another_update() takes exactly 2 arguments (1 given)

      >

      > clearly it isn't seeing it as a method, just an attribute which happens

      > to be a function. Is there a preferred way to do this?

      >

      You have a strange definition of "obvious". You say you want to replace

      a method in a *class*, not in an instance of that class ... so just do that:

      |>> class This(object):

      ... def update(self,val):

      ... print val

      ...

      |>> def another_update(obj,val):

      ... print "another",val

      ...

      |>> This.update = another_update

      |>> t = This()

      |>> t.update(42)

      another 42

      Cheers,

      John

      #1; Wed, 07 May 2008 19:11:00 GMT
    • Brian Blais a crit :

      > Hello,

      > I want to replace a method in a class during run-time with another

      > function. I tried the obvious, but it didn't work:

      > class This(object):

      > def update(self,val):

      > print val

      > def another_update(obj,val):

      > print "another",val

      > t=This()

      > t.update(5)

      > t.update=another_update

      This is not "replacing a method in a class", but replacing it in an

      instance.

      > t.update(5) # this one doesn't work, gives

      > # TypeError: another_update() takes exactly 2 arguments (1 given)

      > clearly it isn't seeing it as a method, just an attribute which happens

      > to be a function. Is there a preferred way to do this?

      import types

      t.update = types.MethodType(another_update)

      #2; Wed, 07 May 2008 19:12:00 GMT
    • I don't know a ton about this, but it seems to work if you use:

      This.update = another_update

      (instead of t.update = another_update)

      after saying This.update = another_update, if you enter This.update, it

      says <unbound method This.another_update>, (it's unbound)

      but if you call

      t.update(5)

      it will print:

      another 5

      #3; Wed, 07 May 2008 19:13:00 GMT
    • Le mardi 27 juin 2006 01:14, Brian Blais a =E9crit=A0:

      > t=3DThis()

      > t.update(5)

      > t.update=3Danother_update

      > t.update(5) =A0# this one doesn't work, gives

      > # TypeError: another_update() takes exactly 2 arguments (1 given)

      >

      > clearly it isn't seeing it as a method, just an attribute which happens to

      > be a function. =A0Is there a preferred way to do this?

      Yes, this is because you assigned it to the instance, not the class, it sho=

      uld=20

      be :

      t=3DThis()

      t.update(5)

      This.update=3Danother_update

      t.update(5)

      In OOP Methods are defined in *classes* not in any arbitrary object (ie.=20

      instances). You can learn more on how it works in python reading about the=

      =20

      descriptor protocol of new style class (__getattribute__ special method).

      To clearly understand what belongs to class and what belongs to instances,=

      =20

      try :

      u=3DThis()

      t.prop =3D None

      t.prop

      u.prop

      This.other_prop =3D None

      t.other_prop, u.other_prop=20

      This.__dict__.items()

      t.__dict__, u.__dict__

      =2D-=20

      _____________

      Maric Michaud

      _____________

      Aristote - www.aristote.info

      3 place des tapis

      69004 Lyon

      Tel: +33 426 880 097

      #4; Wed, 07 May 2008 19:14:00 GMT
    • Le mardi 27 juin 2006 05:05, Bruno Desthuilliers a =E9crit=A0:

      > import types

      > t.update =3D types.MethodType(another_update)

      This works with :

      t.update =3D types.MethodType(another_update, t)

      Oh, this *really* misleading what the intent of the programmer is, and=20

      In [29]: t.update

      Out[29]: <bound method ?.<lambda> of <__main__.a instance at 0xa774d96c>>

      all let think it's a method defined in t's class.

      I prefer early binding with default parameters :

      In [30]: def another_update(self, param) :pass

      ...:

      In [31]: t.update =3D lambda x, self=3Dt : another_update(self, x)

      In [32]: t.update =3D lambda x, self=3Dt, func=3Danother_update : func(self=

      , x)

      In [33]: t.update

      Out[33]: <function <lambda> at 0xa7744aac>

      So we have a function and know it (probably) belongs to the instance.

      =2D-=20

      _____________

      Maric Michaud

      _____________

      Aristote - www.aristote.info

      3 place des tapis

      69004 Lyon

      Tel: +33 426 880 097

      #5; Wed, 07 May 2008 19:15:00 GMT
    • Maric Michaud a crit :

      > Le mardi 27 juin 2006 05:05, Bruno Desthuilliers a crit :

      >

      >

      > This works with :

      > t.update = types.MethodType(another_update, t)

      oops ! too fast on the send button :(

      And thanks for the correction.

      #6; Wed, 07 May 2008 19:16:00 GMT
    • Maric Michaud a crit :

      (snip)

      > In OOP Methods are defined in *classes* not in any arbitrary object

      Chapter and verse, please ? AFAIK, the first O in OOP stands for

      "object", not for "class" !-)

      Classes are just an implementation convenience, and the fact that the

      class-based model is the most usual one doesn't imply it's the only

      valid one. So there's no reason one shouldn't override (or add) a method

      on a per-object basis. As a matter of fact, it's perfectly legal (and

      can be very convenient) to do so in Python.

      #7; Wed, 07 May 2008 19:17:00 GMT
    • Le mardi 27 juin 2006 06:21, Bruno Desthuilliers a =E9crit=A0:

      > Maric Michaud a =E9crit :

      > (snip)

      >

      > Chapter and verse, please ? AFAIK, the first O in OOP stands for

      > "object", not for "class" !-)

      >

      Hard to find it, indeed.

      > Classes are just an implementation convenience, and the fact that the

      > class-based model is the most usual one doesn't imply it's the only

      > valid one.

      Maybe, never been told of another one, do you think of javascript prototype=

      s ?=20

      Well, there are no methods in this model, only functions.

      > So there's no reason one shouldn't override (or add) a method=20

      > on a per-object basis. As a matter of fact, it's perfectly legal (and

      > can be very convenient) to do so in Python.

      I never saw the term "method" used for anything except for what it means fo=

      r=20

      classes, and moreover, the class model, even if it's just an implementation=

      ,=20

      it's the one chosen by python.

      =46or the common understanding of the model, IMHO, classes bind methods,=20

      instances bind functions.

      =2D-=20

      _____________

      Maric Michaud

      _____________

      Aristote - www.aristote.info

      3 place des tapis

      69004 Lyon

      Tel: +33 426 880 097

      #8; Wed, 07 May 2008 19:18:00 GMT
    • Maric Michaud wrote:

      > Le mardi 27 juin 2006 06:21, Bruno Desthuilliers a crit :

      >

      > Hard to find it, indeed.

      >

      > Maybe, never been told of another one, do you think of javascript prototypes ?[/co

      lor]

      There other prototype-based languages. And truth is that while having

      classes, Python's object model is much more closer to javascript's one

      than to Java or C++.

      > Well, there are no methods in this model, only functions.

      Nope. There are closures, not simple functions.

      And FWIW, what do you think methods are in Python ? Yes, functions,

      wrapped in a special descriptor.

      >

      > I never saw the term "method" used for anything except for what it means f

      or

      > classes,

      Help on class instancemethod in module __builtin__:

      class instancemethod(object)

      | instancemethod(function, instance, class)

      |

      | Create an instance method object.

      > and moreover, the class model, even if it's just an implementation,

      > it's the one chosen by python.

      There's a superficial similarity with "mainstream" static OOPLs like

      Java/C++ etc. But Python's classes, and their relation to instances, are

      as dynamic as can be, and really very different from what's in most books.

      > For the common understanding of the model, IMHO, classes bind methods,

      > instances bind functions.

      ?

      In Python, a class is nothing more than an object that:

      1/ act as an object factory

      2/ serves as delegatee for instances.

      FWIW, the proper constructor (__new__, not __init__) is free to return

      instances of any other class (as long as the initializer signature is

      compatible).

      bruno desthuilliers

      python -c "print '.python.todaysummary.com.'.join(['.'.join([w[::-1] for w in p.split('.')]) for

      p in 'onurb.python.todaysummary.com.xiludom.gro'.split('.python.todaysummary.com.')])"

      #9; Wed, 07 May 2008 19:19:00 GMT