Getting a function name from string

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • David Rasmussen

    #1

    Getting a function name from string

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

    def someFunction():
    print "Hello"

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

    /David
  • Paul McGuire

    #2
    Re: Getting a function name from string

    "David Rasmussen" <david.rasmusse n@gmx.net> wrote in message
    news:436943e0$0 $2083$edfadb0f@ dtext02.news.te le.dk...[color=blue]
    > If I have a string that contains the name of a function, can I call it?
    > As in:
    >
    > def someFunction():
    > print "Hello"
    >
    > s = "someFuncti on"
    > s() # I know this is wrong, but you get the idea...
    >
    > /David[/color]

    Lookup the function in the vars() dictionary.
    [color=blue][color=green][color=darkred]
    >>> def fn(x):[/color][/color][/color]
    .... return x*x
    ....[color=blue][color=green][color=darkred]
    >>> vars()['fn'][/color][/color][/color]
    <function fn at 0x009D67B0>[color=blue][color=green][color=darkred]
    >>> vars()['fn'](100)[/color][/color][/color]
    10000

    -- Paul


    Comment

    • Mike Meyer

      #3
      Re: Getting a function name from string

      "Paul McGuire" <ptmcg@austin.r r._bogus_.com> writes:[color=blue]
      > "David Rasmussen" <david.rasmusse n@gmx.net> wrote in message
      > news:436943e0$0 $2083$edfadb0f@ dtext02.news.te le.dk...[color=green]
      >> If I have a string that contains the name of a function, can I call it?
      >> As in:
      >>
      >> def someFunction():
      >> print "Hello"
      >>
      >> s = "someFuncti on"
      >> s() # I know this is wrong, but you get the idea...
      >>
      >> /David[/color]
      >
      > Lookup the function in the vars() dictionary.
      >[color=green][color=darkred]
      >>>> def fn(x):[/color][/color]
      > ... return x*x
      > ...[color=green][color=darkred]
      >>>> vars()['fn'][/color][/color]
      > <function fn at 0x009D67B0>[color=green][color=darkred]
      >>>> vars()['fn'](100)[/color][/color]
      > 10000[/color]

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

      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
      --
      Mike Meyer <mwm@mired.or g> http://www.mired.org/home/mwm/
      Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.

      Comment

      • Steven D'Aprano

        #4
        Re: Getting a function name from string

        David Rasmussen wrote:
        [color=blue]
        > If I have a string that contains the name of a function, can I call it?
        > As in:
        >
        > def someFunction():
        > print "Hello"
        >
        > s = "someFuncti on"
        > s() # I know this is wrong, but you get the idea...[/color]

        py> eval("someFunct ion()")
        '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 = "someFuncti on"
        eval(s)()

        you can pass around the function as an object:

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



        --
        Steven.

        Comment

        • Bengt Richter

          #5
          Re: Getting a function name from string

          On Wed, 02 Nov 2005 19:01:46 -0500, Mike Meyer <mwm@mired.or g> wrote:
          [color=blue]
          >"Paul McGuire" <ptmcg@austin.r r._bogus_.com> writes:[color=green]
          >> "David Rasmussen" <david.rasmusse n@gmx.net> wrote in message
          >> news:436943e0$0 $2083$edfadb0f@ dtext02.news.te le.dk...[color=darkred]
          >>> If I have a string that contains the name of a function, can I call it?
          >>> As in:
          >>>
          >>> def someFunction():
          >>> print "Hello"
          >>>
          >>> s = "someFuncti on"
          >>> s() # I know this is wrong, but you get the idea...
          >>>
          >>> /David[/color]
          >>
          >> Lookup the function in the vars() dictionary.
          >>[color=darkred]
          >>>>> def fn(x):[/color]
          >> ... return x*x
          >> ...[color=darkred]
          >>>>> vars()['fn'][/color]
          >> <function fn at 0x009D67B0>[color=darkred]
          >>>>> vars()['fn'](100)[/color]
          >> 10000[/color]
          >
          >vars() sans arguments is just locals, meaning it won't find functions
          >in the global name space if you use it inside a function:
          >[color=green][color=darkred]
          >>>> def fn(x):[/color][/color]
          >... print x
          >...[color=green][color=darkred]
          >>>> def fn2():[/color][/color]
          >... vars()['fn']('Hello')
          >...[color=green][color=darkred]
          >>>> fn2()[/color][/color]
          >Traceback (most recent call last):
          > File "<stdin>", line 1, in ?
          > File "<stdin>", line 2, in fn2
          >KeyError: 'fn'[color=green][color=darkred]
          >>>>[/color][/color]
          >
          >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.[/color]
          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

          Comment

          • Mike Meyer

            #6
            Re: Getting a function name from string

            bokr@oz.net (Bengt Richter) writes:[color=blue][color=green]
            >>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.[/color]
            > IMO it would be nice if name lookup were as cleanly
            > controllable and defined as attribute/method lookup.
            > Is it a topic for py3k?[/color]

            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.ite ms():
            self.variables[name] = var.get()
            self.variables['calculate']()
            for name, var in self.outputs.it ems():
            var.set(self.va riables[name])

            def run(self):
            self.app.mainlo op(self.calcula te)


            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
            --
            Mike Meyer <mwm@mired.or g> http://www.mired.org/home/mwm/
            Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.

            Comment

            Working...