hofer a écrit :
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(self,dly):
print "VERBOSE",
threading._Event.wait(self,dly)
Note that given your use case, you could have used a decorator here
instead...
def verbose(method):
def _verbose(*args, **kw):
print "%s called on %s" % (method.__name__, method.im_self)
print "args : ", args, " - kwargs : ", kw
return method(*args, **kw)
_verbose.__name__ = "verbose wrapper for %s" % method.__name__
return _verbose
b.wait = verbose(b.wait)
Or if you want a more extensible - and "reversible" - solution:
class VerboseMethod(object):
def __init__(self, method, before=None, after=None):
# we only want bound methods here
obj = getattr(method, "im_self", None)
if obj is None:
err = "%s expected a bound method, got %s" % (
type(self), method
)
raise ValueError(err)
self._method = method
self._before = before
self._after = after
def _verbose_before(self, *args, **kw):
"""
You subclass VerboseMethod and taylor this to your own needs,
or alternatively pass a 'before' callback to VerboseMethod
that will get called with method, *args, **kw
"""
if callable(self._before):
self._before(self._method, *args, **kw)
return
# default
m = self._method
print "%s about to be called on %s" % (m.__name__, m.im_self)
print "args : ", args, " - kwargs : ", kw
def _verbose_after(self, result, *args, **kw):
"""
You subclass VerboseMethod and taylor this to your own needs,
or alternatively pass an 'after' callback to VerboseMethod
that will get called with method, result, *args, **kw
"""
if callable(self._after):
self._after(self._method, result, *args, **kw)
return
# default
m = self._method
print "%s called on %s" % (m.__name__, m.im_self)
print "args : ", args, " - kwargs : ", kw
print "result : ", result
def __call__(self, *args, **kw):
self._verbose_before(*args, **kw)
result = self._method(*args, **kw)
self._verbose_after(result, *args, **kw)
return result
def drop(self):
"""restore the original method..."""
obj = self._method.im_self
delattr(obj, self._method.__name__)
class B(object):
def __init__(self, name):
self.name = name
def wait(self, dly=42):
return "%s.wait(%s)" % (self.name, dly)
b1 = B('b1')
b2 = B('b2')
print b1.wait()
print b2.wait()
b1.wait = VerboseMethod(b1.wait)
print b1.wait()
print b2.wait()
b1.wait.drop()
print b1.wait()
print b2.wait()
def before(m, *args, **kw):
print "test before"
print m, args, kw
def after(m, r, *args, **kw):
print "test after"
print m, r, args, kw
b1.wait = VerboseMethod(b1.wait, before=before, after=after)
print b1.wait()
print b2.wait()
b1.wait.drop()
print b1.wait()
print b2.wait()
HTH
--
http://mail.python.org/mailman/listinfo/python-list