replace mothod for only one object but not for a class

George Sakkis george.sakkis at gmail.com
Tue Oct 14 22:59:42 CEST 2008


On Oct 14, 12:28 pm, Bruno Desthuilliers
<bdesth.quelquech... at free.quelquepart.fr> wrote:
> George Sakkis a écrit :
>
>
>
> > On Oct 14, 1:50 pm, hofer <bla... at dungeon.de> wrote:
> >> 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?
>
> >> Example
> >> ##### This is NOT what I'd like to do
> >> ##### as it overwrites the method for all objects of this class
> >> o1 = aclass()
> >> o2 = aclass()
> >> # call original method
> >> o1.method()
> >> o2.method()
> >> # overwrite the method for the entire class
> >> aclass.method = mymethod
> >> o1.method() # now new method
> >> o2.method() # now new method
>
> >> ####### What doesn't work, but what I'd like to do
> >> o1 = aclass()
> >> o2 = aclass()
> >> # call original method
> >> o1.method()
> >> o2.method()
> >> # overwrite the method for the entire class
> >> o1.method = mymethod
> >> o1.method() # now new method
> >> o2.method() # still old method
>
> >> thanks for any pointers.
>
> > Please post the actual code that doesn't work. The following works as
> > expected:
>
> >     >>> class A(object):
> >     ...     def foo(self): return 'Original'
> >     ...
> >     >>> a = A()
> >     >>> b = A()
> >     >>> a.foo()
> >     'Original'
> >     >>> b.foo()
> >     'Original'
> >     >>> b.foo = lambda: 'Modified'
> >     >>> a.foo()
> >     'Original'
> >     >>> b.foo()
> >     'Modified'
>
> Except that b.foo is a plain function, not a method:
>
>  >>> class A(object):
> ...     def foo(self): return "original called on %s" % self
> ...
>  >>> a = A()
>  >>> b = A()
>  >>> a.foo()
> 'original called on <__main__.A object at 0xb7c0c56c>'
>  >>> b.foo()
> 'original called on <__main__.A object at 0xb7c0c4ec>'
>  >>> b.foo = lambda: "modified called on %s" % self
>  >>> b.foo
> <function <lambda> at 0xb7bfe9cc>
>  >>> b.foo()
> Traceback (most recent call last):
>    File "<stdin>", line 1, in <module>
>    File "<stdin>", line 1, in <lambda>
> NameError: global name 'self' is not defined
>  >>> b.foo = lambda self: "modified called on %s" % self
>  >>> b.foo()
> Traceback (most recent call last):
>    File "<stdin>", line 1, in <module>
> TypeError: <lambda>() takes exactly 1 argument (0 given)
>  >>>

You're right of course; that's what you get with minimal testing ;)
Still it works with a small modification, binding self to b as default
argument:

b.foo = lambda self=b: "modified called on %s" % self

The functools.partial() solution shown before is the generalization of
this for more than one arguments. So I'm wondering, except for the
callable's exact type (bound method vs function vs functools.partial
object) is there any other difference and a reason to prefer one over
the other ? If not, functools.partial() seems more readable than
calling explicitly the descriptor.

George



More information about the Python-list mailing list