Functions, callable objects, and bound/unbound methods

Ron Garret rNOSPAMon at flownet.com
Fri Dec 1 03:03:34 EST 2006


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:

>>> c1.m1
<unbound method c1.f>
>>> c1().m1
<bound method c1.f of <__main__.c1 instance at 0x51e738>>
>>> c1().m1()
<__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

>>> setattr(c1, 'm2', callable())
>>> c1.m2
<__main__.callable instance at 0x51e738>
>>> c1().m2
<__main__.callable instance at 0x51e738>
>>> c1().m2()
((), {})

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



More information about the Python-list mailing list