replace mothod for only one object but not for a class

Bruno Desthuilliers bdesth.quelquechose at free.quelquepart.fr
Tue Oct 14 18:45:45 CEST 2008


hofer a écrit :
> Hi,
> 
> I have multiple objects all belonging to the same class
>  (which I didn't implement and whose code I don't want to modify)
> 
> Now I'd like to change one method for one object only (after it has
> been created) without adding any overhead
> to the call of the other object's methods.
> 
> 
> Is this possible?

Yes.

If the class is a new-style one [1], it just requires invoking the 
descriptor protocol by yourself to get a bound method, ie:

 >>> class A(object):
...     def foo(self): return "original %s" % self
...
 >>> a = A()
 >>> b = B()
 >>> def new_foo(self): return "modified %s" % self
...
 >>> b.foo = new_foo.__get__(b, type(b))
 >>> b.foo()
'modified <__main__.B instance at 0xb7c0ce4c>'
 >>>

If it's a classic class, you can get by using either new.instancemethod 
or types.MethodType:

 >>> class B:
...     def bar(self): return "bar %s" % self
...
 >>> a = B()
 >>> b = B()
 >>> def new_bar(self): return "new bar %s" % self
...
 >>> import new
 >>> b.bar = new.instancemethod(new_bar, b, type(b))
 >>> b.bar()
'new bar <__main__.B instance at 0xb7c0c4ec>'
 >>> a.bar()
'bar <__main__.B instance at 0xb7c0c74c>'
 >>> import types
 >>> b.bar = types.MethodType(new_bar, b, type(b))
 >>> b.bar
<bound method instance.new_bar of <__main__.B instance at 0xb7c0c4ec>>
 >>> b.bar()
'new bar <__main__.B instance at 0xb7c0c4ec>'
 >>> a.bar()
'bar <__main__.B instance at 0xb7c0c74c>'
 >>>

Note that using either new.instancemethod or types.MethodType will also 
work with new-style classes - it just requires an additional import !-)


[1] for a new style class, type(cls) will return type. For a "classic" 
class, type(cls) will return classobj.


HTH

(snip)
> 
> P.S. I guess, that there is a computer science term for what I try to
> achieve.
> If anybody knew it I would be interested to learn it as well.

I don't know of any "official" cs term for this. In prototype-based 
OOPL's, setting attributes on a per-object basis is just ordinary 
programming. Python is class-based, but on some (if not a lot) of 
aspects it's quite close to prototype-based languages.

An unofficial cs term is "monkeypatching". It's usually understood as a 
per-class or per-module replacement, but is still appropriate for a 
per-object replacement (or addition FWIW).




More information about the Python-list mailing list