473,549 Members | 2,329 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

replace mothod for only one object but not for a class

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.
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.

Oct 14 '08 #1
10 1435
from functools import partial

class Point:
def __init__(self, x, y):
self.x, self.y = x, y

def show(self, n):
for i in range(n):
print "Point: (%s, %s)" % (self.x, self.y)

def new_method(obj, func):
def method(*args, **kw):
return func(obj, *args, **kw)

return method
p1 = Point(1, 2)
p2 = Point(3, 4)

def show(self, n):
print "Not a Point: %s-%s" % (self.x, self.y)
p2.show = partial(show, p2)

p1.show(3)
p2.show(3)

HTH,
--
Miki <mi*********@gm ail.com>
http://pythonwise.blogspot.com
Oct 14 '08 #2
On Oct 14, 1:50 pm, hofer <bla...@dungeon .dewrote:
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'
HTH,
George
Oct 14 '08 #3
On Oct 14, 11:20*am, George Sakkis <george.sak...@ gmail.comwrote:
On Oct 14, 1:50 pm, hofer <bla...@dungeon .dewrote:
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'

HTH,
George
What you're doing is called monkeypatching. I consider it dangerous,
but to each his own. Python's metaprogramming facilities can handle
it.

The lambda approach can leak, I've had garbage collection issues when
shuffling around bound methods (my objects weren't being collected
when expected, basically). The partial approach is cool, too, but it
won't reliably work with things like __getattr__ and __setattr__,
which I also learned the hard way. The probable best way of going
about it is to define a new class that implements your one method, and
use some on-the-fly magic to create a NEW class that inherits from
both your monkeypatch class and your current instance's class:

In [2]: class main_implementa tion(object):
...: def a(self):
...: print 'a'
...: def b(self, argb='b'):
...: print 'B says %r' % argb
...:
...:

In [6]: class new_implementat ion_of_a(object ):
...: def a(self):
...: print "This is a new implementation of A"
...:
...:

In [7]: mymain = main_implementa tion()

In [8]: mymain.a()
a

In [9]: mymain.__class_ _ = type(mymain.__c lass__.__name__ +'MODIFIED',
(new_implementa tion_of_a, mymain.__class_ _), {})

In [10]: mymain
Out[10]: <__main__.main_ implementationM ODIFIED object at 0x0137EA50>

In [11]: mymain.a()
This is a new implementation of A

In [12]: mymain.b()
B says 'b'

The magic here occurs when you create a new class on-the-fly using the
type() built-in function and assign it to the instance's __class__
attribute.

Good luck.
Oct 14 '08 #4
Bruno Desthuilliers wrote:
If the class is a new-style one [1], it just requires invoking the
descriptor protocol by yourself to get a bound method, ie:
Another note about new style classes:
You can NOT overwrite most magic methods (__*__) on the instance. Most
magic methods are only looked up on the class object.

Christian

Oct 14 '08 #5
On Oct 14, 12:28 pm, Bruno Desthuilliers
<bdesth.quelque ch...@free.quel quepart.frwrote :
George Sakkis a écrit :
On Oct 14, 1:50 pm, hofer <bla...@dungeon .dewrote:
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 <lambdaat 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.parti al() 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.parti al
object) is there any other difference and a reason to prefer one over
the other ? If not, functools.parti al() seems more readable than
calling explicitly the descriptor.

George
Oct 14 '08 #6
George Sakkis a écrit :
(snip)
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
Ok, now with a real use case : use a named function instead of a lambda,
and define the function before having access to b !-)
The functools.parti al() 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.parti al
object) is there any other difference and a reason to prefer one over
the other ?
Consistency ? Possibly performances (NB : not benchmarked - might be
worth a little homework to check this out) ?
If not, functools.parti al() seems more readable than
calling explicitly the descriptor.
Perhaps is it just me starting to getting senile and resistant to new
ideas, but while it does indeed work, I see the partial() solution as a
WTF. Invoking function.__get_ _ *is* the obvious[1] way to get a bound
method from a function.

[1] for anyone that know how Python turns functions into methods, that is...

But indeed, methods are specialized partial applications, and your
solution is perfectly valid.
Oct 15 '08 #7
Bruno Desthuilliers a écrit :
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:
(snip)

If it's a classic class, you can get by using either new.instancemet hod
or types.MethodTyp e:
Either I'm starting to get old or I need some vacations... Manually
invoking function.__get_ _(obj, type(obj)) also work with classic
classes, of course.

(snip)
Oct 15 '08 #8
On Oct 14, 7:50*pm, hofer <bla...@dungeon .dewrote:
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.

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.

Thanks a lot this works.
Though I must admint, that even after reading the doc I don't really
understand why.
Oct 15 '08 #9
Hi
hofer a écrit :
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.
Thanks for all of your answers:

Here an example with three of the suggested solutions:
(I didn't succeed in implementing Jason's solution with my
example)

############### ############### ############### ###########
import threading
# some objects
a = threading.Event ()
b = threading.Event ()
c = threading.Event ()
d = threading.Event ()

def run_dly(o): # a test function
print o,"start",
o.wait(1)
print "stop"

# unmodified test
run_dly(a)
run_dly(b)
run_dly(c)
run_dly(d)

# The new Method
def verbose_wait(se lf,dly):
print "VERBOSE",
threading._Even t.wait(self,dly )

### Implemented with partial
from functools import partial
b.wait = partial(verbose _wait,b)

### with __get__ for new classes
c.wait = verbose_wait.__ get__(c,type(c) )

## with new for old classes
import new
d.wait = new.instancemet hod(verbose_wai t,d,type(d))

run_dly(a)
run_dly(b)
run_dly(c)
run_dly(d)
############# end
thanks again

Hofer

Oct 15 '08 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
3672
by: beliavsky | last post by:
The code for text in open("file.txt","r"): print text.replace("foo","bar") replaces 'foo' with 'bar' in a file, but how do I avoid changing text inside single or double quotes? For making changes to Python code, I would also like to avoid changing text in comments, either the '#' or '""" ... """' kind.
9
3110
by: gulu man | last post by:
Hi, What is the substitute for COM objects in .NET? How can I create something similar to com in .net? Is it still possible? Thank you
5
11339
by: Mahesha | last post by:
Hello, I need help in replacing one string pattern with another. Ex: I have a financial security expression like log(T 3.25 6/24/2004)/sqrt(T 4.5 6/19/2002) Here "T 3.25 6/24/2004" is a variable on which I need to perform log and then divide the result with 3.980. While parsing such expressions, I need to find all occurence of date...
16
6147
by: BBM | last post by:
This is so bizarre I hesitate to post it, but I need to get this working. My code looks like this... Private Const cmdTestResourcesSel = "SELECT * FROM TResources" & _ " WHERE Scenario = @Scenario" Dim cmdstr as String cmdstr = cmdTestResourcesSel
23
1924
by: digitalorganics | last post by:
How can an object replace itself using its own method? See the following code: class Mixin: def mixin(object, *classes): NewClass = type('Mixin', (object.__class__,) + classes, {}) newobj = NewClass() newobj.__dict__.update(object.__dict__) return newobj
3
1981
by: aspineux | last post by:
Hi I would like a kind of function able to replace the base class like that: class Graph: pass class Circle(Graph): pass
10
1892
by: Steven W. Orr | last post by:
In the program below, I want this instance to end up calling repmeth whenever inst.m1 is called. As it is now, I get this error: Hello from init inst = <__main__.CC instance at 0x402105ec> Traceback (most recent call last): File "./foo9.py", line 17, in ? inst.m1() TypeError: repmeth() takes exactly 1 argument (0 given)
1
3383
by: NvrBst | last post by:
I want to use the .replace() method with the regular expression /^ %VAR % =,($|&)/. The following DOESN'T replace the "^default.aspx=,($|&)" regular expression with "": --------------------------------- myStringVar = myStringVar.replace("^" + iName + "=,($|&)", ""); --------------------------------- The following DOES replace it though:...
6
1355
by: Rauan Maemirov | last post by:
Hi, all. I'm trying to replace <object ...><embed... /></objectwith <imgtag and vice-verse. It's like implementation of media plugin of Tiny MCE editor. I tried to watch their code, but it's too complicated and has a lot of unnecessary code. And the main reason is i'm weak in javascript rewriting. :) I need just simple rewrite for e.g. this...
0
7546
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7740
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
7985
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7503
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
7830
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
1
5387
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
5111
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3496
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
784
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.