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

8 投票
4 回答
15494 浏览
提问于 2025-04-17 10:56
from moduleA import ClassA

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

假设我在 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 的类变量。这样,当你调用类似 A.calling_method() 的时候,就能正确地调用在 moduleB.py 中定义的方法。

我看到在 StackOverflow 上有些回答提到,可以在实例化 ClassA 后使用 types.MethodType 来进行这种绑定,但我还没有找到如何在类定义内部进行绑定的方法,这样在类实例化时就能自动完成。

如果有人能给我一些关于 bind_method 方法应该怎么写的建议,我将非常感激。

4 个回答

3

因为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 
5

跳过那些我不太明白的配置部分,绑定的内容看起来是这样的:

from moduleB import meth2
ClassA.meth1 = meth2

这里最重要的是,你绑定的是类,而不是某个具体的实例。这样,如果你在一个实例上调用 meth1 方法,它会自动把这个实例作为第一个参数传进去。

7
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

当然可以!请把你想要翻译的内容发给我,我会帮你用简单易懂的语言解释清楚。

撰写回答