misantroop
misantroop

Reputation: 2544

Passing class and its function into another class

I'm looking to pass a class and it's methods into a class. I have no problem with passing the class as it's accessible during instance initiation but the methods (when passed separately) are not.

The non-functional example is simplified a lot and only the classes Caller and Callable could be modified, the initial call should remain unmodified. I would prefer to not go with exec or eval if at all possible.

class Caller(object):
    def __init__(self, **kwargs):
        super(Caller, self).__init__()
        self.klass = kwargs.get('klass', None)
        self.func = kwargs.get('func', None)
        self.klassParams = kwargs.get('klassParams', None)

    def call(self):
        klass = self.klass(**self.klassParams)

        # Call the function
        someFunc = self.func
        klass.someFunc()

class Callable(object):
    def __init__(self, **kwargs):
        super(Callable, self).__init__()

    def someFunction():
        pass

c = Caller(klass=Callable, func=someFunction, klassParams={'some':'param'})
c.call()

This will obviously fail with NameError: name 'someFunction' is not defined

Upvotes: 1

Views: 60

Answers (1)

Shubham Sharma
Shubham Sharma

Reputation: 71689

You can use the getattr bulit in function in python, here is how you can use it,

getattr(object, name[, default])

Return the value of the named attribute of object. name must be a string. If the string is the name of one of the object’s attributes, the result is the value of that attribute. For example, getattr(x, 'foobar') is equivalent to x.foobar. If the named attribute does not exist, default is returned if provided, otherwise AttributeError is raised.

I have made quite a few corrections to your code, so now the code will work fine,

class Caller(object):
    def __init__(self, parent=None, **kwargs):
        # Calling object class constructor doesn't take the argument name parent as its the base class in python
        super(Caller, self).__init__()
        self.klass = kwargs.get('klass', None)
        self.func = kwargs.get('func', None)
        self.klassParams = kwargs.get('klassParams', None)

    def call(self):
        klass = self.klass(**self.klassParams)

        # Call the function
        someFunc = self.func
        getattr(klass, someFunc)()

class Callable(object):
    def __init__(self, some=None, parent=None):
        # Calling object class constructor doesn't take the argument name parent as its the base class in python
        super(Callable, self).__init__()

    def someFunction(self):
        print("someFunction called by Caller")
        pass

# You have to pass the string representating the name of function to be called, in this case pass `'someFunction'`    
c = Caller(klass=Callable, func='someFunction', klassParams={'some':'param'})
c.call()

The output will be,

someFunction called by Caller

Upvotes: 1

Related Questions