Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic Method Call In Python 2.7 using strings of method names

I have a tuple which lists down the methods of a class like:

t = ('methA','methB','methC','methD','methE','methF')

and so on..

Now I need to dynamically call these methods based on a user made selection. The methods are to be called based on the index. So if a user selects '0', methA is called, if '5', methF is called.

My method for doing this is as follows:

def makeSelection(self, selected):
    #methodname = t[selected]
    #but as this is from  within the class , it has to be appended with 'self.'methodname
    # also need to pass some arguments locally calculated here

I have managed to work out something with eval but it yields error and is not at all elegant.

like image 700
bhaskarc Avatar asked Jul 18 '13 21:07

bhaskarc


1 Answers

If you're calling a method on an object (including imported modules) you can use:

getattr(obj, method_name)(*args) #  for this question: use t[i], not method_name

for example:

>>> s = 'hello'
>>> getattr(s, 'replace')('l', 'y')
'heyyo'

If you need to call a function in the current module

getattr(sys.modules[__name__], method_name)(*args)

where args is a list or tuple of arguments to send, or you can just list them out in the call as you would any other function. Since you are in a method trying to call another method on that same object, use the first one with self in place of obj

getattr takes an object and a string, and does an attribute lookup in the object, returning the attribute if it exists. obj.x and getattr(obj, 'x') achieve the same result. There are also the setattr, hasattr, and delattr functions if you want to look further into this kind of reflection.



A completely alternative approach:
After noticing the amount of attention this answer has received, I am going to suggest a different approach to what you're doing. I'll assume some methods exist

def methA(*args): print 'hello from methA'
def methB(*args): print 'bonjour de methB'
def methC(*args): print 'hola de methC'

To make each method correspond to a number (selection) I build a dictionary mapping numbers to the methods themselves

id_to_method = {
    0: methA,
    1: methB,
    2: methC,
}

Given this, id_to_method[0]() would invoke methA. It's two parts, first is id_to_method[0] which gets the function object from the dictionary, then the () calls it. I could also pass argument id_to_method[0]("whatever", "args", "I", "want) In your real code, given the above you would probably have something like

choice = int(raw_input('Please make a selection'))
id_to_method[choice](arg1, arg2, arg3) # or maybe no arguments, whatever you want
like image 139
Ryan Haining Avatar answered Oct 17 '22 22:10

Ryan Haining