Python:用于延迟函数调用的装饰器

时间:2015-07-24 20:42:42

标签: 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的地方。我不明白为什么会发生这种情况,因为在我调用Foo的时候,我只希望得到一个lambda,后来调用时会调用newFn,而不是立即调用newFn。我是否正在为更有经验的python用户做一些明显的事情,是否有更好的方法来获得我想要的东西? (我已经尝试过屈服而不是回归,但也没有办法让这项工作成功,而且我已经玩了functools部分但我发现自己用空的kwargs调用函数)

1 个答案:

答案 0 :(得分:1)

听起来好像你想要的是functools.partial装饰者。它完全符合Foo函数的功能,但更为一般。

根据你的评论,你也可以使用一个类来做你想要的更多pythonic:

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)

你可以将这些方法作为callables传递:

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

do_something(a.foo_helper)