tags:

views:

445

answers:

7

This was the best name I could come up with for the topic and none of my searches yielded information relevant to the question.

How do I call a function from a string, i.e.

functions_to_call = ["func_1", "func_2", "func_3"]

for f in functions_to_call:
    call f
+1  A: 
functions_to_call = ["func_1", "func_2", "func_3"]

for f in functions_to_call:
    eval(f+'()')

Edited to add:

Yes, eval() generally is a bad idea, but this is what the OP was looking for.

Chris Upchurch
This works perfectly, I'm not sure why it has so few upvotes.
Teifion
-1 for not mentioning that the use of eval is a bad idea overall.
nosklo
indeed. There is no reason to use eval() here; `locals()[f]()` would have done fine. That's still a very questionable way of doing it, but way better than eval().
bobince
getattr works better using strings, which is ALSO what the OP was looking for. We shouldn't be spreading eval() when getattr() will do the job just as well.
gregturn
@nosklo, Does every answer really need to mention that eval is bad? It would probably suffice if you just picked apart the atrocity that is the eval function in your own answer.
tgray
@tgray: In my opinion, teaching a newbie to use eval like that is a bad thing, and should be downvoted.
nosklo
@nosklo, point taken... see comment on your answer for a follow-up question.
tgray
I'm well aware of the evils of eval, I came across it in PHP a few years ago. Thank you though for your concern.
Teifion
+1 for ATFQ. Other answers have pointed out the problems with eval and suggested alternatives, but it's still worth knowing about it.
dF
+15  A: 

how do you not know the name of the function to call? Store the functions instead of the name:

functions_to_call = [int, str, float]

value = 33.5

for function in functions_to_call:
    print "calling", function
    print "result:", function(value)
nosklo
I could explain all about the exact program but I felt it'd be a waste of space and distract from the specific problem at hand.
Teifion
The functions are stored as strings in the question, not so in your answer, so the answer isn't exactly right...
sykora
@sykora ... but it does show a better way if you can twist the requirements of your problem a bit.
Aaron Maenpaa
@Teifion: I think if you explained your exact problem instead of your failed attempt to solve it, you'd get better suggestions. Storing function names as strings and running them with eval/exec is a bad idea overall. There are always other better options.
nosklo
+1: Do not store the function names; store the functions themselves.
S.Lott
@nosklo, would you mind going into more detail as to *why* eval is bad? Or link to a resource that explains it...
tgray
@tgray: Use of eval is slower, allows arbritary code execution, and shows a bad design. Maybe you should open a new top-level question about the issue.
nosklo
+1  A: 

See the eval and compile functions.

This function can also be used to execute arbitrary code objects (such as those created by compile()). In this case pass a code object instead of a string. If the code object has been compiled with 'exec' as the kind argument, eval()‘s return value will be None.

lothar
-1 for not mentioning that the use of exec/eval is a bad idea overall.
nosklo
+7  A: 

Something like that...when i was looking at function pointers in python..

def myfunc(x):
    print x

dict = {
    "myfunc": myfunc
}

dict["myfunc"]("hello")

func = dict.get("myfunc")
if callable(func):
    func(10)
LB
+1 dispatch dicts are a good way to do it if you really need to have a string
nosklo
"function pointers"? No such thing.
Devin Jeanpierre
yep...i know...I was looking for something equivalent...
LB
+1 for the idea (which also allows one to restrict the callable stuff to a specific set), but virtual -1 for calling the dictionary "dict", which will hide the type name in the local scope...
RaphaelSP
could you explain it to me a little more ? thanks :-)
LB
Every dictionary is an instance of the type "dict". It can be be build two ways: either using the syntax {}, or by calling the constructor "dict()". Calling a variable (or anything) "dict" prevents you from building a dictionary by calling "dict()", and from testing the type.
RaphaelSP
Of course, this also applies to any other built-in type, and "dict" by itself is not that important. But still.
RaphaelSP
+17  A: 

You can use the python builtin locals() to get local declarations, eg:

def f():
    print "Hello, world"

def g():
    print "Goodbye, world"

for fname in ["f", "g"]:
    fn = locals()[fname]
    print "Calling %s" % (fname)
    fn()

You can use the "imp" module to load functions from user-specified python files which gives you a bit more flexibility.

Using locals() makes sure you can't call generic python, whereas with eval, you could end up with the user setting your string to something untoward like:

f = 'open("/etc/passwd").readlines'
print eval(f+"()")

or similar and end up with your programming doing things you don't expect to be possible. Using similar tricks with locals() and dicts in general will just give attackers KeyErrors.

Anthony Towns
you're a vicious jerk nosklo. he *did* explain it quite well
Mark
@Mark: indeed. I commented the wrong answer, sorry. Removed.
nosklo
+6  A: 

Have a look at the getattr function:

http://docs.python.org/library/functions.html?highlight=getattr#getattr

import sys

functions_to_call = ["func_1", "func_2", "func_3"]

for f in functions_to_call:
  getattr(sys.modules[__name__], f)()
marcog
+1  A: 

Don't use eval! It's almost never required, functions in python are just attributes like everything else, and are accessible either using getattr on a class, or via locals():

>>> print locals()
{'__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__name__': '__main__',
 'func_1': <function func_1 at 0x74bf0>,
 'func_2': <function func_2 at 0x74c30>,
 'func_3': <function func_3 at 0x74b70>,
}

Since that's a dictionary, you can get the functions via the dict-keys func_1, func_2 and func_3:

>>> f1 = locals()['func_1']
>>> f1
<function func_1 at 0x74bf0>
>>> f1()
one

So, the solution without resorting to eval:

>>> def func_1():
...     print "one"
... 
>>> def func_2():
...     print "two"
... 
>>> def func_3():
...     print "three"
... 
>>> functions_to_call = ["func_1", "func_2", "func_3"]
>>> for fname in functions_to_call:
...     cur_func = locals()[fname]
...     cur_func()
... 
one
two
three
dbr