1

Here is my problem I have a number of functions defined and I want to loop through a list of these functions and run them one at a time in the correct order.

def one():
    print "One "

def two():
    print "Two "

def three(): "Three "
    print "Three "

arr = ('one','two','three')

for fnc in arr:
    <some how run the function name in the variable fnc>

Any Help Appreciated, as I am a beginner with python and django.

Stephen Brown
  • 564
  • 1
  • 9
  • 23

4 Answers4

9

Python functions are first order objects; just put them in the sequence:

arr = (one, two, three)

for fnc in arr:
    fnc()

You could store strings too, but then you need to turn those back into the function object first. That'd just be extra busywork you don't really need to do.

You can still turn strings into objects; the globals() function gives you the current global namespace as a dictionary, so globals()['one'] gives you the object referenced by the name one, but this would also give you access to every global in your module; if you then made a mistake it could lead to hard to track bugs or even security holes (as end-users could potentially abuse functions you didn't intent to be called).

If you really need to map names to functions, because, say, you need to take input from something else that only produces strings, use a predefined dictionary:

functions = {
    'one': one,
    'two': two,
    'three': three,
}

and map your string to the function:

function_to_call = 'one'
functions[function_to_call]()

Your function names do not need to match the string values here. By using a dedicated dictionary you limit what can be called.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • The OP has functions' *names*, not objects – vaultah May 30 '15 at 17:37
  • @vaultah: yes, but their *goal* is to call the functions in a specific order. They tried to solve that by putting the names of the functions in a sequence, but the problem is better solved by storing the functions themselves. – Martijn Pieters May 30 '15 at 17:38
  • @Velimir: please don't add solutions to my answer; you are free to post your own if you wish, but you'll never find me advocating `eval()`. – Martijn Pieters May 30 '15 at 17:58
  • I tried the equivalent of fnc() in my django app but got 'unicode' object is not callable. [code] req_section.name() [/code]. – Stephen Brown May 30 '15 at 18:20
  • @StephenBrown: so what is `req_section` and what is `req_section.name`? The latter is a *unicode string*. That's not a function. – Martijn Pieters May 30 '15 at 18:24
  • This fails: func = 'carousel' [and then] context['sections'] = func(request) [but this] context['sections'] = carousel(request) [works]. req_section is an instance of a model and name is an attribute. – Stephen Brown May 30 '15 at 18:34
  • @StephenBrown: `func` is not a function. It is a string. – Martijn Pieters May 30 '15 at 18:35
  • It is a string containing the name of the function (def) I want to run. I tried it this way after trying the __unicode__. Neither it as __unicode__ or str work like this. – Stephen Brown May 30 '15 at 18:38
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/79216/discussion-between-stephen-brown-and-martijn-pieters). – Stephen Brown May 30 '15 at 18:41
1

It depends on where the functions are defined, but if they are in the current context, you can get a reference to them by retrieving them from the globals function:

def fn():
   return ":)"

for f in['fn']:
    print globals()[f]()
Gerard van Helden
  • 1,601
  • 10
  • 13
0

Seems to work...

            method_name = 'one'
            possibles = globals().copy()
            possibles.update(locals())
            method = possibles.get(method_name)
            if not method:
                raise Exception("Method %s not implemented" % method_name)
            returned_value = method()
Stephen Brown
  • 564
  • 1
  • 9
  • 23
0

For your specific example, simply use eval:

arr = ('one','two','three')

for fnc in arr:
    eval(fnc + '()')

Be aware that using eval() is considered bad practice by some.

Community
  • 1
  • 1
Velimir Mlaker
  • 10,664
  • 4
  • 46
  • 58