Getting a function name from string

  • Thread starter David Rasmussen
  • Start date
D

David Rasmussen

If I have a string that contains the name of a function, can I call it?
As in:

def someFunction():
print "Hello"

s = "someFunction"
s() # I know this is wrong, but you get the idea...

/David
 
M

Mike Meyer

Paul McGuire said:
David Rasmussen said:
If I have a string that contains the name of a function, can I call it?
As in:

def someFunction():
print "Hello"

s = "someFunction"
s() # I know this is wrong, but you get the idea...

/David

Lookup the function in the vars() dictionary.
... return x*x
...
10000

vars() sans arguments is just locals, meaning it won't find functions
in the global name space if you use it inside a function:
.... print x
.... .... vars()['fn']('Hello')
.... Traceback (most recent call last):
File "<stdin>", line 1, in ?

Using globals() in this case will work, but then won't find functions
defined in the local name space.

For a lot of uses, it'd be better to build the dictionary by hand
rather than relying on one of the tools that turns a namespace into a
dictionary.

<mike
 
S

Steven D'Aprano

David said:
If I have a string that contains the name of a function, can I call it?
As in:

def someFunction():
print "Hello"

s = "someFunction"
s() # I know this is wrong, but you get the idea...

py> eval("someFunction()")
'Hello'
py> eval(s)() # note the second pair of brackets
'Hello'

See also exec -- but before you use either eval or
exec, make sure you are fully aware of the security
implications. Whatever a user could do to your system
by sitting down in front of it with a Python
interactive session open and typing commands at the
keyboard, they can also do remotely if you call exec on
input they provide.

So you probably don't want to be calling exec on
strings that you get from random users via a website.

It has been my experience that, more often than not,
any time you think you want to evaluate strings, you
don't need to.

For instance, instead of passing around the name of the
function as a string:

s = "someFunction"
eval(s)()

you can pass around the function as an object:

s = someFunction # note the lack of brackets
s()
 
B

Bengt Richter

Paul McGuire said:
David Rasmussen said:
If I have a string that contains the name of a function, can I call it?
As in:

def someFunction():
print "Hello"

s = "someFunction"
s() # I know this is wrong, but you get the idea...

/David

Lookup the function in the vars() dictionary.
def fn(x):
... return x*x
...
vars()['fn']
vars()['fn'](100)
10000

vars() sans arguments is just locals, meaning it won't find functions
in the global name space if you use it inside a function:
... print x
... ... vars()['fn']('Hello')
... Traceback (most recent call last):
File "<stdin>", line 1, in ?

Using globals() in this case will work, but then won't find functions
defined in the local name space.

For a lot of uses, it'd be better to build the dictionary by hand
rather than relying on one of the tools that turns a namespace into a
dictionary.
IMO it would be nice if name lookup were as cleanly
controllable and defined as attribute/method lookup.
Is it a topic for py3k?

Regards,
Bengt Richter
 
M

Mike Meyer

IMO it would be nice if name lookup were as cleanly
controllable and defined as attribute/method lookup.
Is it a topic for py3k?

I'm not sure what you mean by "cleanly controllable and defined". I'd
say name lookup is well defined and clean, as it's the same as it is
in pretty much any language that supports nested scopes, modulo
assignment creating things in the local scope. If you're talking about
letting users control that mechanism, that's definitely py3k material,
if not "python-like-language-that's-not-python" material. On the other
hand, if you just want to provide tools that let users do name lookups
the way they can do attribute lookups, that's easy, and we could add
that now:

getname(name) - returns the object name is bound to.
setname(name, value) - binds the variable name.

And maybe you want an optional third argument of a callable, which
causes the functions to work on names starting in the callables name
space.

The real question is (as always) - what's the use case? In particular,
what's the use case that we really want to encourage? As I said,
you're usually better off separating dynamically built names into
their own dictionary rather than trying to plug them into - or pull
them out of - one of the language namespaces. If you plug them in,
there's no way to get them back out except by mechanisms similar to
how you got them in, so you might as well let those mechanisms include
a dictionary. If you pull it out, you might as well have referenced
the bare name rather than the string. If you constructed the name in
some way, then changing the constructor to do a dictionary lookup
should be straightforward. All of these technics avoid problems that
come from overloading a language namespace.

Of course, I'm not omniscient, so you may have something that doesn't
fit those cases in mind - in which case, let's hear about it.

You can even arrange to run python code with your dictionary as a
namespace. Following are excerpts from a tool I'm currently not
working on.

class P:
def __init__(self):
self.variables = dict(In = self.set_input, Out = self.set_output,
Labels = self.set_labels, Float = DoubleVar,
String = StringVar, Int = IntVar)

def calculate(self):
for name, var in self.inputs.items():
self.variables[name] = var.get()
self.variables['calculate']()
for name, var in self.outputs.items():
var.set(self.variables[name])

def run(self):
self.app.mainloop(self.calculate)


def main(args):
app = P()
execfile(argv[1], app.variables)
app.run()

Here I create a dictionnary - P().variables - and populate it with
names and their values. I then run the code of interest with that
dictionary as the global namespace. The code will add things to the
namespace - in particular, "calculate". I then run a loop which will,
at unspecified times, set names in the P().variables dictionary, run
the "calculate" callable created by the code of interest, then copy
values out of the dictionary. This works ilke a charm. If you don't
want to deal with entire files, you can use exec, or even eval if you
just want to get a value back.

<mike
 

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

Forum statistics

Threads
474,270
Messages
2,571,341
Members
48,029
Latest member
Anchorman2022

Latest Threads

Top