如何通过函数返回* args,** kwargs

时间:2018-12-07 07:00:14

标签: python python-3.x

带有参数列表和关键字参数的简单函数:

def foo(*args, **kwargs):
    print(args, kwargs)

我可以按以下方式调用此函数

foo('foo', 'bar', 'baz', hoge='H', fuga='F')

l = ['foo', 'bar']
kw = {'hoge': 'H', 'fuga': 'F'}
foo(*l, **kw)

问题:我可以通过其他函数传递参数吗?

foo(produce_arg())

我正在通过单击https://palletsprojects.com/p/click/编写CLI脚本。 几个子命令具有相同的选项:

@click.group()
def cli():
    pass

@cli.command()
@cli.option('--target', type=str, ...)
@cli.option('--exec', is_flag=True, ...)
...
def foo():
    pass

@cli.command()
@cli.option('--target', type=str, ...)
...
def bar():
    pass

@cli.command()
@cli.option('--exec', is_flag=True, ...)
...
def baz():
    pass

...

我认为它不是DRY,所以我要写如下:

def definition_of(optname):
    # so magical code!

@click.group()
def cli():
    pass

@cli.command()
@cli.option(definition_of('target'))
@cli.option(definition_of('exec'))
...
def foo():
    pass

@cli.command()
@cli.option(definition_of('target'))
...
def bar():
    pass

@cli.command()
@cli.option(definition_of('exec'))
...
def baz():
    pass

...

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

要直接解决您的问题:是的,您可以通过另一个函数传递参数:

a, k = produce_arg()
foo(*a, **k)

此过程可以通过某种方式“隐藏”:

def pass_a_k(func, ak):
    return func(*ak[0], **ak[1])
pass_a_k(foo, produce_arg())

将是一种方法,

def pass_a_k(func, a, k):
    return func(*a, **k)
pass_a_k(foo, *produce_arg())

方法会稍有不同。

两者都使用辅助函数来调用目标函数。

def pass_a_k(func, a, k):
    return func(*a, **k)
def adapt_a_k(func):
    # here, maybe fool around with functools.wraps etc.
    return lambda a, k: func(*a, **k)
adapt_a_k(foo)(*produce_arg())

(或其相应的对等物)将是另一种方法。在这里,如果您更需要保留“自适应”功能将很有帮助。

在您的示例中,可能是

cli_option_a_k = adapt_a_k(cli.option)

@cli_option_a_k(*definition_of('target'))
@cli_option_a_k(*definition_of('exec'))
...
def foo():
    pass

甚至

cli_option_by_optname = lambda optname: adapt_a_k(cli.option)(*definition_of(optname))
cli_option_by_optname = lambda optname: pass_a_k(cli.option, *definition_of(optname))

@cli_option_by_optname('target')
@cli_option_by_optname('exec')
...
def foo():
    pass