programmatically calling a function

D

Dave Ekhaus

hi

i'd like to call a python function programmatically - when all i have
is the functions name as a string. i.e.


fnames = ['foo', 'bar']

for func in fnames:

#
# how do i call function 'func' when all i have is the name of the
function ???
#



def foo():

print 'foo'

def bar():

print 'bar'


i'd really appreciate any help the 'group' has to offer.


thanks
dave
 
P

Peter Hansen

Dave said:
i'd like to call a python function programmatically - when all i
have is the functions name as a string. i.e.
>
fnames = ['foo', 'bar']

The usual answer at this point is to say that functions are
"first class objects" in Python, which basically means you
can haul around references to them instead of having to
refer to them indirectly with strings. This isn't always
possible, but see if this might be something you can do instead:

funcs = [foo, bar] # note: no quotation marks!

for func in funcs:
func(1, 2, 3) # call each function, passing three arguments...
for func in fnames:
# how do i call function 'func' when all i have is the name of the
function ???

To convert from the name to a reference, you'll still need access
to the functions, so often you don't really need to use the names
approach. Still, if you must, all you need to know is what namespace
the functions are defined in. If they're local to the current module,
you can use globals(), which returns a dictionary of global names
that you can index using the name:

fnames = ['foo', 'bar']
for name in fnames:
func = globals()[name]
func(1, 2, 3) # call function with three arguments, or whatever


-Peter
 
D

Doug Schwarz

Dave Ekhaus said:
hi

i'd like to call a python function programmatically - when all i have
is the functions name as a string. i.e.


fnames = ['foo', 'bar']

for func in fnames:

#
# how do i call function 'func' when all i have is the name of the
function ???
#



def foo():

print 'foo'

def bar():

print 'bar'


i'd really appreciate any help the 'group' has to offer.


thanks
dave


Dave,

I think eval might be what you're looking for:

f = eval('len')
length = f([1,2,3])


By the way, are you the Dave Ekhaus I used to work with at Kodak?
 
R

Reinhold Birkenfeld

Doug said:
Dave,

I think eval might be what you're looking for:

f = eval('len')
length = f([1,2,3])

But only if the string given to eval is checked thorougly for allowed
contents. Better use getattr.

Reinhold
 
D

Doug Schwarz

Reinhold Birkenfeld said:
Doug said:
Dave,

I think eval might be what you're looking for:

f = eval('len')
length = f([1,2,3])

But only if the string given to eval is checked thorougly for allowed
contents. Better use getattr.

Reinhold


Actually, upon reading Peter Hansen's reply more carefully, I wil defer
to his approach, namely,

def foo():
print "foo"

f = globals()["foo"]

as I suspect that it will be more efficient. You still need to make
sure that the string in question is one of the keys in the globals()
dictionary or else handle the error -- just as with eval.

I don't see how getattr solves the original problem. What, exactly, is
the first argument to getattr?
 
R

Reinhold Birkenfeld

Doug said:
Dave,

I think eval might be what you're looking for:

f = eval('len')
length = f([1,2,3])

But only if the string given to eval is checked thorougly for allowed
contents. Better use getattr.

Actually, upon reading Peter Hansen's reply more carefully, I wil defer
to his approach, namely,

def foo():
print "foo"

f = globals()["foo"]

as I suspect that it will be more efficient. You still need to make
sure that the string in question is one of the keys in the globals()
dictionary or else handle the error -- just as with eval.

Well, with eval, you need to really check the string before calling
eval, with globals() you just need to catch an KeyError, which is cheaper.
I don't see how getattr solves the original problem. What, exactly, is
the first argument to getattr?

If run at the toplevel, __main__. If the functions are in a module, this
module. But you are right, globals() is more understandable.

However, if the use case is as in the OP's example, Peter Hansen's first
approach is surely the fastest and most concise.


Reinhold
 
C

Carl Banks

Doug said:
I don't see how getattr solves the original problem. What, exactly, is
the first argument to getattr?


mod = __import__(__this__)
f = getattr(mod,"foo")

I tend to prefer this over globals() because it seems a little less
magical to me, especially when setting a global. Either this or
gloabls() will work fine. Please don't use eval for stuff like this:
that's not what it's for and it has the potential to be dangerous.
 
L

Larry Bates

I see lots of others have made suggestions, but here is a method
that I use frequently:

define a dictionary that contains references to your functions:

def foo():
..
.. whatever it does
..

def bar():
..
.. whatever it does
..



xfer={'foo', foo, 'bar', bar}

Then you can write

for fname in fnames:
xfer[fname](args)

May not be what you want, but seems like it is from your description.

-Larry
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,222
Messages
2,571,137
Members
47,754
Latest member
Armand37T7

Latest Threads

Top