Search code examples
pythonpython-2.7classgetattrhasattr

Using getattr to call a function in a separate class


I may be trying to do something that is outside of the realm of possibility here, but I figured I would ask first before abandoning hope. So here it goes...

I have 2 classes, A and B. Each class has an arbitrary number of functions. Class B will be instantiated somewhere in Class A and Class A will utilize one of Class B functions via that instantiation. A function in Class B will need to refer to one or more of Class A's functions using it's current instantiation data of Class A.

Class A

#!/usr/bin/python
from classB import classB


class classA(object):
    def Apple(self):
        print("Inside Apple")
        b = classB()
        b.Banana()
        b.bar()

    def foo(self): 
        print("foo inside apple")


a = classA()
a.Apple()

Class B:

#!/usr/bin/python
import inspect


class classB(object):
    def Banana(self):
        print("Inside banana")

    def bar(self):
        print("bar inside banana")

        ''' 
        The following lines just show I can get the names of the
        calling class and methods.
        '''
        stack = inspect.stack()
        the_class = stack[1][0].f_locals["self"].__class__
        the_method = stack[1][0].f_code.co_name
        print("Caller Class: {}".format(the_class))
        print("Caller Method: {}".format(the_method))

        function_name = 'foo'
        if hasattr(the_class, function_name):
            print("Class {} has method {}".format(the_class, 
            function_name))
            getattr(the_class, function_name)()

I get the following error:

getattr(the_class, function_name)()

TypeError: unbound method foo() must be called with classA instance as first argument (got nothing instead)

Thanks!


Solution

  • As the error suggests, you must build an object of classA (i.e. the_class) before calling getattr on it.

    objA = the_class()
    

    But taking a step back, why don't you just pass class A to class B while initializing it?

    b = classB(self)
    

    That will allow you to access the exact method of class A that you need.

    Else, if method 'foo' in class A is supposed to be a static method, make it so by using @staticmethod decorator.