Reputation: 385
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?
Upvotes: 1
Views: 1769
Reputation: 19329
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
Upvotes: 1