This is a concept that I’ve encountered over and over, mostly while writing unit tests. Every time it has crossed my plate, I’ve looked at code like this:

Python 2.5.1 (r251:54863, Apr 15 2008, 22:57:26) 
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> class A(object):
...   def boo(self):
...     print "boo"
... 
>>> def foo(self):
...   print "foo"
... 
>>> a = A()
>>> a.boo
<bound method A.boo of <__main__.A object at 0x819b0>>
>>> a.boo = foo
>>> a.boo
<function foo at 0x7ea70>

And have come to a conclusion like “well, there’s a difference between bound methods and normal functions”. Then I end up on a wild goose chase, looking at classes and stuff:

>>> b = A()
>>> b.boo
<bound method A.boo of <__main__.A object at 0x818f0>>
>>> b.boo.__class__
<type 'instancemethod'>
>>> foo.__class__
<type 'function'>
>>>

From here, I reach the conclusion that I need to figure out how to instantiate an ‘instancemethod’. On previous days, this has led to frustration — but not today! Finally today, with the help of Ryan Baldwin, I feel satisfied that I understand one more aspect of Python.

First, by looking at the ‘instancemethod’ object, you can see that there’s three attributes: ‘im_class’, ‘im_func’, and ‘im_self’.

>>> dir(b.boo)
['__call__', '__class__', '__cmp__', '__delattr__', '__doc__', '__get__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'im_class', 'im_func', 'im_self']

This makes sense — a bound ‘instancemethod’ need to have access to its function object (im_func), its instance (im_self), and its containing class (im_class). So my first attempt was to just swap out the im_func:

>>> b.boo.im_func = foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: readonly attribute

Well then. Looks like that won’t work.

Some Googling got me to http://docs.python.org/library/types.html#module-types, where all was revealed.

The types module has a MethodType object, that takes three parameters: types.MethodType(function, instance, class). That sure sounds like the parameters on an ‘instancemethod’ from above.

>>> import types
>>> b.boo = types.MethodType(foo, b, A)
>>> b.boo()
foo

Tada!