简体   繁体   中英

How to pass (multiple) regex parsed function parameters to a python function

I'm trying to build a python class that parses a string and if it matches a regex that looks like a function call attempt to call that function on the class, passing in any parameters.

For example a string like "foo("a", 20")" would translate to something like self.foo("a", 20).

Here is the code that I have so far..

class FooTranslate(object):
    def create_string(self, letter, size):
        return letter*size

    def run_function(self, func_str):
        match = re.match("([\w_]+)\((|[\W\d\w\,]+)\)", func_str)
        if match == None:
            print "Couldn't match a regex!"
            return False
        else:
            func, fargs = match.groups()

        try:
            if fargs == "":
                return self.__getattribute__(func)()
            else:
                return self.__getattribute__(func)(eval(fargs))
        except AttributeError, e:
            print "Invalid function call: %s" % (func)
            return False

This code works in the basic cases...

In [1018]: foot = FooTranslate()
In [1019]: foot.run_function("foo()")
Foo!
In [1020]: foot.run_function("bar(2)")
FooFoo

However in the case of using 2 argument functions:

In [1021]: foot.run_function("create_string('a', 2)")

in run_function(self, func_str)
     24                 return self.__getattribute__(func)()
     25             else:
---> 26                 return self.__getattribute__(func)(eval(fargs))
     27         except AttributeError, e:
     28             print "Invalid function call: %s" % (func)

TypeError: create_string() takes exactly 3 arguments (2 given)

The reason why is that the eval() call returns fargs as a tuple, which create_string() takes as only a single argument. Any idea how I can pass a variable number of arguments through to a function call? Or have a better alternative way to do this?

You can use the * operator to explode a tuple into separate arguments to a function. For example:

def f(a, b, c):
    print a, b, c

If I call f(...) like this:

f((1,2,3))

I get an error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() takes exactly 3 arguments (1 given)

But if I call it like this:

f(*(1,2,3))

I get:

1 2 3

The * operator will even work if the function takes a variable number of arguments. For example, given the following function:

def f2(a, b, *args):
    print a, b,
    for x in args:
        print x,
    print

If I call f2(*(1,2,3,4,5)) it prints:

1 2 3 4 5

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM