6

我有以下代码:

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

4 回答 4

9

catch-all*args参数必须在任何显式参数之后:

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

如果您还将 catch-all**kw关键字参数添加到定义中,则必须*args参数之后:

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

混合显式关键字参数和包罗万象的*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参数可以放在关键字参数之前,但这具有的含义。通常,可以在调用签名中将关键字参数指定为位置参数(例如,调用您的函数,就像foo(somefunc, 'argument')分配'argument'给一样named_arg)。通过在位置参数和命名参数之间放置*args或放置一个平原*,您可以将命名参数排除在位置参数之外;调用foo(somefunc, 'argument')会引发异常。

于 2012-12-11T14:28:07.937 回答
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。

于 2012-12-11T14:32:47.747 回答
1

将参数的顺序更改为:

def foo(func, named_arg = None, *args):
    return func(*args)
于 2012-12-11T14:29:21.503 回答
1

根据文档,不:

教程第 4.7.2 节说:

在函数调用中,关键字参数必须跟在位置参数之后。

...和​​4.7.3 说关于“任意参数列表”:

在可变数量的参数之前,可能会出现零个或多个正常参数。

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

  1. 位置参数
  2. 命名参数
  3. 变量/任意参数
于 2012-12-11T14:30:24.507 回答