JoshAdel JoshAdel - 3 months ago 16
Python Question

Dynamically bind method to class instance in python

Let's say that I have a class defined in

moduleA.py
which I want to add a method to, using some sort of loader method that takes a the name of a second module and the method defined there that should be bound

class ClassA(object):
def __init__(self,config):
super(ClassA, self).__init__()

self.a = 1
self.b = 2
self.meth1 = self. bind_method(config)

def bind_method(self,config):
# load method
<return method defined in config as a str 'moduleB.meth2'>

def calling_method():
return self.meth1()


where the method defined in
moduleB.py
looks something like:

def meth2(self):
return self.a + self.b


The point being that I want to be able to write
meth2
to be able to access class variables of
ClassA
once it is bound. This way, when you would have something like:

from moduleA import ClassA

A = ClassA()
aout = A.calling_method()


Calling
A.calling_method()
properly calls the method defined in
moduleB.py
.

I've seen this sort of binding done in answers on SO after
ClassA
is instantiated using
types.MethodType
, but I haven't been able to dig up how to bind inside the class definition so that it is done internally when the class is instantiated.

Any suggestions on what should go in the
bind_method
method would be much appreciated.

Answer
import sys
import types

def getobj(astr):
    """
    getobj('scipy.stats.stats') returns the associated module
    getobj('scipy.stats.stats.chisquare') returns the associated function
    """
    try:
        return globals()[astr]
    except KeyError:
        try:
            return __import__(astr, fromlist=[''])
        except ImportError:
            modname, _, basename = astr.rpartition('.')
            if modname:
                mod = getobj(modname)
                return getattr(mod, basename)
            else:
                raise

class ClassA(object):
    def __init__(self, methpath):
        super(ClassA, self).__init__()
        self.a = 1
        self.b = 2
        self.meth1 = types.MethodType(getobj(methpath), self)

a = ClassA('moduleB.meth2')
print(a.meth1())
# 3