Add bound methods to instantiated objects in Python

In Python, as in other dynamic languages, you can add new methods to a class after it’s been defined. You can define a function just as you would inside the class body, then assign that function to an attribute of the class:

class C:
    pass # No methods... yet

def foo(self):
    print(self)

C.foo = foo

This will result in foo being added to the class as if it had been inside the class block.

Upon access, in Python 2, it will be wrapped in an unbound method object, while in Python 3 it will just be a function. The difference is more than an implementation detail: in Python 3 you can call C.foo(2) and it will print 2, whereas in Python 2 you’ll get an exception if the first argument is not a C instance.

When you create an instance of C and get its foo property, what you’ll get back is a bound method, which is another wrapper object. This means that you can’t just add a function to an instance of a class and expect it to work properly.

instance = C()

def bar(self):
    print(self)

instance.bar = bar
instance.bar()  # error, `self` is not passed in

Instead, you need to first convert the function into a bound method of the object yourself.

instance.bar = bar.__get__(instance, instance.__class__)