0

I am trying to call an uncertain named function from another class. I mean, external input or a variable in a loop as a function name.

For example;

class options(object):

    def functionOne(): # or function1
        pass
    def functionTwo(): # or function2
        pass
    def functionThree(): # or function3
        pass

in a options.py file and either:

class main(object):

    def runSomething():

        options=options()
        while counter<=3:
            options.function**"a"**()
            counter = counter+1

or:

class main(object):

    def runSomething():

        options=options()
        num=raw_input("number: ")

        options.function**"num"**()

in the main.py.

What should I put at the bold places? Is there any way to combine function name and number in order to call function.

I have been looking for a solution to this problem for days, but I cannot find any relevant solution.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Alnus
  • 13
  • 2

3 Answers3

3

Here is one approach:

function_num = getattr(options, 'function'+str(num))
function_num()

This uses the getattr builtin function. getattr(a, 'b') is equivalent to a.b, where a is some object and b is some attribute of that object.

senshin
  • 10,022
  • 7
  • 46
  • 59
  • It is the basic method that I'm looking for **exactly**. Thank you so much for your interest. – Alnus Jan 11 '14 at 02:22
2

This is really the same as dynamically creating and accessing variables, even if those variables happen to be functions rather than, say, integers. See Keep data out of your variable names and Why you don't want to dynamically create variables for some idea of why this is generally a bad idea.

Now, if these functions had useful names that you were actually going to call statically in your code, that would be a different story. But the fact that they're called function1, function2, etc., and that you want to call them in some way resembling options.function**"num"**(), implies that this is exactly the case.

So, the answer is the same as it is anywhere else: Put the things into a list or dict, and look them up from there.

The fact that forgot to give these things to have a self parameter implies that you've only crammed them into a class to have somewhere to store them. In which case… why not just store them in a list in the first place? For example:

class Options(object):
    functions = []
    def function1(self): pass
    functions.append(function1)
    def function2(self): pass
    functions.append(function2)
    def function3(self): pass
    functions.append(function3)

class main(object):
    def runSomething():
        options=Options()
        for counter in range(3):
            options.functions[counter]()

Of course you don't want to repeat yourself by typing function1 in the definition and then again in the functions.append. How can you solve that? With a decorator. This may be a little too advanced for you to figure out on your own, and the details will depend on how you actually want to use these things (which isn't clear from your question, given those methods-without-self definitions), but once you get the idea it's very flexible and not that hard:

_optfunctions = []
class Options(object):
    functions = _optfunctions
    def add(func):
        _optfunctions.append(func)
        return func
    @add
    def function1(self): pass
    @add
    def function2(self): pass
    @add
    def function3(self): pass
    del add
del _optfunctions
abarnert
  • 354,177
  • 51
  • 601
  • 671
1
class Options(object):
    def functionOne(self): # or function1
        print 'one'
    def functionTwo(self): # or function2
        print 'two'
    def functionThree(self): # or function3
        print 'three'

o = Options()
for name in dir(o):
    if 'function' in name:
        getattr(o, name)()

When executed, the above results in:

one
three
two

To run a function selectively given a partial name:

def run_it(o, partial):
    for name in dir(o):
        if partial in name:
            getattr(o, name)()

This can be used as:

>>> run_it(o, 'One')
one
>>> run_it(o, 'nTwo')
two
John1024
  • 109,961
  • 14
  • 137
  • 171