在python中使用named / unnamed和variable参数进行函数调用

时间:2012-12-11 14:18:49

标签: python

我有以下代码:

def foo(func, *args, named_arg = None):
    return func(*args)

返回SyntaxError

  File "tester3.py", line 3
    def foo(func, *args, named_arg = None):
                                 ^

为什么?是否有可能以某种方式定义一个函数,它接受一个参数(func),然后在命名参数之前获取变量参数列表args?如果没有,我的可能性是什么?

4 个答案:

答案 0 :(得分:6)

全能*args参数必须在任何显式参数之后:

def foo(func, named_arg=None, *args):

如果您还要将全部**kw关键字参数添加到定义中,那么 会出现在*args参数之后:

def foo(func, named_arg=None, *args, **kw):

混合使用显式关键字参数和catch-all *args参数确实会导致意外行为;你不能同时使用任意位置参数明确命名你同时列出的关键字参数。

func以外的任何额外位置首先用于named_arg,它也可以作为位置参数:

>>> def foo(func, named_arg = None, *args):
...     print func, named_arg, args
... 
>>> foo(1, 2)
1 2 ()
>>> foo(1, named_arg=2)
1 2 ()
>>> foo(1, 3, named_arg=2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() got multiple values for keyword argument 'named_arg'
>>> foo(1, 2, 3)
1 2 (3,)

这是因为foo()的任何第二个位置参数将始终用于named_arg

在Python 3中,*args参数可以放在关键字参数之前,但它具有 new 含义。通常,可以在呼叫签名中将关键字参数指定为位置参数(例如,将foo(somefunc, 'argument')调用您的函数将'argument'分配给named_arg)。通过在位置参数和命名参数之间放置*args或普通*,可以排除命名参数用作位置参数;调用foo(somefunc, 'argument')会引发异常。

答案 1 :(得分:2)

不,Python 2不允许这种语法。

您的选择是:

1)将命名的arg移动到*args之前:

def foo(func, named_arg = None, *args):
   ...

2)使用**kwargs

def foo(func, *args, **kwagrs):
   # extract named_arg from kwargs
   ...

3)升级到Python 3。

答案 2 :(得分:1)

将参数的顺序更改为:

def foo(func, named_arg = None, *args):
    return func(*args)

答案 3 :(得分:1)

根据文件,没有:

教程section 4.7.2说:

  

在函数调用中,关键字参数必须遵循位置   参数。

...和4.7.3 says关于'任意参数列表':

  

在变量数量的参数之前,零或更多正常   争论可能会发生。

...所以如果你要使用所有三种参数类型,它们需要在序列中

  1. 位置args
  2. 命名为args
  3. 变量/任意args