Как передать (многократные) параметры анализируемой функции в функцию Python - PullRequest
1 голос
/ 23 декабря 2011

Я пытаюсь создать класс python, который анализирует строку и, если он соответствует регулярному выражению, которое выглядит как попытка вызова функции для вызова этой функции в классе, передавая любые параметры.

Например,строка типа "foo (" a ", 20") "будет переводиться в нечто вроде self.foo (" a ", 20).

Вот код, который у меня есть до сих пор ..

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

Этот код работает в основных случаях ...

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

Однако в случае использования двух функций аргумента:

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)

Причина в том, чтоВызов eval () возвращает fargs в виде кортежа, который create_string () принимает как единственный аргумент. Любая идея, как передать переменное число аргументов в вызов функции? Или есть лучший альтернативный способ сделать это?

1 Ответ

1 голос
/ 23 декабря 2011

Вы можете использовать оператор * , чтобы разбить кортеж на отдельные аргументы функции.Например:

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

Если я позвоню f(...) следующим образом:

f((1,2,3))

Я получу ошибку:

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

Но если я назову этоthis:

f(*(1,2,3))

Я получаю:

1 2 3

Оператор * будет даже работать, если функция принимает переменное число аргументов.Например, с учетом следующей функции:

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

Если я позвоню f2(*(1,2,3,4,5)), она напечатает:

1 2 3 4 5
...