Python: декоратор для отложенного вызова функции



Отказ от ответственности: я довольно новичок в python (2 месяца)



У меня есть скрипт, который должен автоматически генерировать нагрузку тестов, и прежде чем делать свое дело, ему нужно проанализировать некоторые данные из конфигурационных файлов. Дело в том, что некоторые из этих данных могут быть известны только позже, когда все конфигурации были прочитаны, проанализированы и обработаны. Мое текущее решение состоит в том, чтобы заполнить файл функциями вида:



def Foo (arg1, arg2, ..., argn) :
return lambda **kwargs : Foo_helper(arg1, arg2, ..., argn, refs = kwargs["refs"], vars = kwargs["vars"])

def Foo_helper(arg1, arg2, ..., argn, **kwargs) :
... some function statements ...


Где я праймирую args от 1 до n, потому что скрипт не знает, какие функции он выполняет зовущий. Это работает, но я ненавижу необходимость определять 2 функции, чтобы иметь возможность вызывать только 1. Мне бы хотелось что-то вроде:



@deferred
def Foo_helper(arg1, arg2, ..., argn, **kwargs) :
... some function statements ...


Но моя попытка пока что формы:



def arg_deferred(fns) :
def newFn(*args, **kwargs) :
fn(*args, **kwargs)
return lambda **kwargs : newFn(*args, kw1 = kwargs["vars"], kw2 = kwargs["refs"], ..., kwn = kwargs["kwn"])


Достает меня ...



return lambda *args, **kwargs : newFn(*args, refs = kwargs["refs"], vars = kwargs["vars"]) 
KeyError: 'refs'


И это происходит в том месте, где я называю Фу. Я не могу понять, почему это происходит, потому что в тот момент, когда я звоню Foo, я только ожидаю получить обратно лямбду, которая при вызове позже вызовет newFn, а не на самом деле вызовет newFn немедленно. Делаю ли я что-то, что для более опытных пользователей python очевидно, есть ли лучший способ получить то, что я хочу? (Я пытался дать вместо возврата, но не нашел способа заставить это работать, и у меня была игра с functools partial, но я обнаружил, что вызываю функцию с пустыми кваргами)
385   1  

1 ответ:

Похоже, что, возможно, то, что вы хотите, - это functools.partial декоратор. Он делает именно то, что делает ваша функция Foo, но в более общем виде.

Основываясь на вашем комментарии, вы также можете использовать класс, чтобы делать то, что вы хотите, который может быть немного более питонским:

class FooHelper(object):
    def __init__(self, arg1, arg2, ..., argn):
        self.arg1 = arg1
        self.arg2 = arg2
        ...
        self.argn = argn

    def __call__(self, **kwargs):
        # ... some function statements ...

foo_helper_inst = FooHelper(conf_arg1, conf_arg2, ..., conf_argn)
foo_helper_inst(refs = 10, vars = 2)

На самом деле, после дальнейшего размышления, наиболее пифонический способ сделать это-создать класс, который представляет вашу конфигурацию, содержащую все методы, которые вам нужны. Что-то например:

class Config(object):
    def __init__(self, arg1, arg2, ..., argn):
        self.arg1 = arg1
        self.arg2 = arg2
        ...
        self.argn = argn

    def foo_helper(self, **kwargs):
        # ... some function statements ...

    def foo_helper2(self, **kwargs):
        # ... some function statements 2 ...

    # ...

    def bar_helper(self, **kwargs):
        # ... some function statements ...

a = Config(conf_arg1, conf_arg2, ..., conf_argn)
a.foo_helper(refs = 10, vars = 2)
a.foo_helper2(foo = 1, baz = 2)
a.bar_helper(goo=3)

И вы можете передать эти методы как вызываемые:

def do_something(foo_func):
    foo_func(refs=10, vars=2)

do_something(a.foo_helper)

Comments

    Ничего не найдено.