replace mothod for only one object but not for a class
Bruno Desthuilliers
bdesth.quelquechose at free.quelquepart.fr
Tue Oct 14 12:45:45 EDT 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