Functions, callable objects, and bound/unbound methods

R

Ron Garret

If I do this:

def f(self): print self

class c1: pass

setattr(c1, 'm1', f)

Then f is automagically transmogrified into the appropriate sort of
method depending on how it is used:
<__main__.c1 instance at 0x51ec60>

Note that m1 gets passed a self argument.

The same automatic transmogrification does not happen if I use an
callable instance instead of an actual function object:

class callable:
def __call__(self, *args, **kw): return args, kw
((), {})

Note that no selfarg has been passed to m2.

The reason I want to do this is that I want to implement a trace
facility that traces only specific class methods. I want to say:

trace(c1.m1)

and have c1.m1 be replaced with a wrapper that prints debugging info
before actually calling the old value of m1. The reason I want that to
be an instance of a callable class instead of a function is that I need
a place to store the old value of the method so I can restore it, and I
don't want to start building a global data structure because that gets
horribly ugly, and a callable class is the Right Thing -- if there's a
way to actually make it work.

Is there? I tried the obvious things (like making callable inherit from
function, and adding im_func and im_self attribuetes) but they didn't
work.

Thanks,
rg
 
D

Duncan Booth

Ron Garret said:
I want to say:

trace(c1.m1)

and have c1.m1 be replaced with a wrapper that prints debugging info
before actually calling the old value of m1. The reason I want that
to be an instance of a callable class instead of a function is that I
need a place to store the old value of the method so I can restore it,
and I don't want to start building a global data structure because
that gets horribly ugly, and a callable class is the Right Thing -- if
there's a way to actually make it work.

Is there? I tried the obvious things (like making callable inherit
from function, and adding im_func and im_self attribuetes) but they
didn't work.

Read "Functions and Methods" in
http://users.rcn.com/python/download/Descriptor.htm

You need to implement a __get__ method on your class.
 
K

Kent Johnson

Ron said:
The reason I want to do this is that I want to implement a trace
facility that traces only specific class methods. I want to say:

trace(c1.m1)

and have c1.m1 be replaced with a wrapper that prints debugging info
before actually calling the old value of m1. The reason I want that to
be an instance of a callable class instead of a function is that I need
a place to store the old value of the method so I can restore it, and I
don't want to start building a global data structure because that gets
horribly ugly, and a callable class is the Right Thing -- if there's a
way to actually make it work.

If the only reason for a callable class is to save a single value (the
original function), you could instead store it as an attribute of the
wrapper function.

Kent
 
K

Kent Johnson

Ron said:
The reason I want to do this is that I want to implement a trace
facility that traces only specific class methods. I want to say:

trace(c1.m1)

and have c1.m1 be replaced with a wrapper that prints debugging info
before actually calling the old value of m1. The reason I want that to
be an instance of a callable class instead of a function is that I need
a place to store the old value of the method so I can restore it, and I
don't want to start building a global data structure because that gets
horribly ugly, and a callable class is the Right Thing -- if there's a
way to actually make it work.

If the only reason for a callable class is to save a single value (the
original function), you could instead store it as an attribute of the
wrapper function.

Kent
 
R

Ron Garret

Kent Johnson said:
If the only reason for a callable class is to save a single value (the
original function), you could instead store it as an attribute of the
wrapper function.

I considered that, and I may yet fall back on it, but 1) I wanted to
understand how these things worked and 2) I need a way to tell when a
method has been traced, and isinstance(method, tracer) seems less
hackish to me than hasattr(method, 'saved_function').

rg
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top