Dynamically bind method to class instance in python

前端 未结 4 1066
野性不改
野性不改 2021-01-06 00:52

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

相关标签:
4条回答
  • 2021-01-06 01:09

    Since meth2() is a function, it is a descriptor and you can bind it by calling the __get__() method.

    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 
    
    0 讨论(0)
  • 2021-01-06 01:09

    There's actually a much simpler way to do this:

    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()
    
    0 讨论(0)
  • 2021-01-06 01:12
    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
    
    0 讨论(0)
  • 2021-01-06 01:24

    Skipping the config stuff which wasn't clear to me, the binding itself would look like this:

    from moduleB import meth2
    ClassA.meth1 = meth2
    

    The important part is that you're binding to the class, not to an instance. This way if you call meth1 on an instance, it will automatically receive the instance as the first argument.

    0 讨论(0)
提交回复
热议问题