在python中将方法动态绑定到类实例

Jos*_*del 6 python metaprogramming dynamic

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() 
Run Code Online (Sandbox Code Playgroud)

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

def meth2(self):
    return self.a + self.b
Run Code Online (Sandbox Code Playgroud)

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()
Run Code Online (Sandbox Code Playgroud)

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.

yak*_*yak 6

跳过我不清楚的配置内容,绑定本身看起来像这样:

from moduleB import meth2
ClassA.meth1 = meth2
Run Code Online (Sandbox Code Playgroud)

重要的部分是您绑定到类,而不是实例。这样,如果您调用meth1一个实例,它将自动接收该实例作为第一个参数。


unu*_*tbu 6

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
Run Code Online (Sandbox Code Playgroud)