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

时间:2012-01-24 00:38:13

标签: python dynamic metaprogramming

假设我有一个在moduleA.py中定义的类,我想添加一个方法,使用某种加载器方法,它取一个第二个模块的名称和那里定义的应绑定的方法

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() 

moduleB.py中定义的方法如下所示:

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

关键是我希望能够编写meth2以便在绑定后能够访问ClassA的类变量。这样,当你有类似的东西时:

from moduleA import ClassA

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

调用A.calling_method()可以正确调用moduleB.py中定义的方法。

在使用ClassA实例化types.MethodType之后,我已经在SO的答案中看到了这种绑定,但我无法挖掘如何在类定义中绑定,以便它是在实例化类时在内部完成的。

我们非常感谢您对bind_method方法应该采用的建议。

4 个答案:

答案 0 :(得分:4)

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

from moduleB import meth2
ClassA.meth1 = meth2

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

答案 1 :(得分:4)

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

答案 2 :(得分:2)

由于meth2()是一个函数,它是一个描述符,你可以通过调用__get __()方法来绑定它。

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

class ClassA(object):
    def __init__(self,config):
        super(ClassA, self).__init__()
        self.a = 1
        self.b = 2
        self.meth1 = config.__get__(self, ClassA)

c = ClassA(meth2)
print c.meth1() #correctly prints 3 

答案 3 :(得分:-2)

实际上有一种更简单的方法:

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

        self.a = 1
        self.b = 2

    from moduleB import meth2 as meth1

    def calling_method():
        return self.meth1()