Python:在kwargs参数的同时按名称传递参数

40
在Python中我们可以这样做:
def myFun1(one = '1', two = '2'):
    ...

然后,我们可以调用该函数,并通过它们的名称传递参数:
myFun1(two = 'two', one = 'one')

另外,我们可以这样做:

def myFun2(**kwargs):
    print kwargs.get('one', 'nothing here')

myFun2(one='one')

所以我想知道是否可能将两种方法结合起来,就像这样:
def myFun3(name, lname, **other_info):
    ...

myFun3(lname='Someone', name='myName', city='cityName', otherInfo='blah')

一般来说,我们可以做哪些组合?

谢谢,对于我的愚蠢问题感到抱歉。


1
请调用一个带有args、kwargs和可选默认参数的Python函数。相关链接:https://dev59.com/U2kw5IYBdhLWcg3wdKbD - mgilson
3个回答

45

总体思路是:

def func(arg1, arg2, ..., kwarg1=default, kwarg2=default, ..., *args, **kwargs):
    ...

你可以使用任意数量的这些符号。 *** 将“吸收”任何未被其他值占用的剩余值。
位置参数(没有默认值)不能通过关键字给出,非默认参数不能跟随默认参数。
请注意,Python 3 还添加了在 * 之后指定仅限关键字参数的功能:
def func(arg1, arg2, *args, kwonlyarg=default):
    ...

你也可以单独使用*def func(a1, a2, *, kw=d):),这意味着不捕获任何参数,但是后面的所有内容都是关键字参数。
因此,如果你在3.x版本中,你可以通过以下方式实现所需的行为:
def myFun3(*, name, lname, **other_info):
    ...

这将允许使用namelname作为仅限关键字的参数进行调用。

请注意,这是一种不寻常的接口,可能会让用户感到烦恼-我只会在非常特定的用例中使用它。

在2.x中,您需要通过解析**kwargs来手动创建它。


小心。我认为你不能在*args之后使用默认参数(至少在Python2.x中不行)。 - mgilson
在Python 2.7中,def test(var, kwarg1=1, *args, **kwargs): ...对我不起作用。它抱怨有多个值用于关键字参数。 - Stephen
1
@Raufio 的问题在于你可能同时使用位置参数和关键字参数填充了 kwarg1,这会为同一个变量提供两个值。例如:test(1, 2, kwarg1=3),此时 kwarg1 应该是 2 还是 3 呢?你可以选择只使用位置参数 test(1, 2) 或只使用关键字参数 test(1, kwarg1=3) - Gareth Latty
1
@Raufio test(1, 10, 1, 2, 3, test=15) -> @Raufio test(1,10,1,2,3,测试=15) - Gareth Latty
1
位置参数(未提供默认值)不能通过关键字给出。实际上,至少对于Python 2.7来说是可能的。关键字参数通过名称分配给位置参数。"对于每个关键字参数,标识符用于确定相应的插槽(如果标识符与第一个形式参数名称相同,则使用第一个插槽,依此类推)"。https://docs.python.org/2/reference/expressions.html#calls - user2745509
显示剩余4条评论

3
你可以将命名参数与kwargs一起添加。如果在调用函数中存在该键,则它将被视为命名参数,否则将由kwargs字典接收。
def add(a=1, b=2,**c):
    res = a+b
    for items in c:
        res = res + c[items]
    print(res)

add(2,3)

5

add(b=4, a =3)

7

add(a =1,b=2,c=3,d=4)

10


2

至少对于Python 2.7是可能的。关键字参数按名称分配给位置参数,因此您可以执行以下操作:

In [34]: def func(name, lname, **kwargs):
    print 'name='+name, 'lname='+lname
    print kwargs
   ....:     

In [35]: func(lname='lname_val', name='name_val', city='cityName', otherInfo='blah')
name=name_val lname=lname_val
{'city': 'cityName', 'otherInfo': 'blah'}

官方文档如下所述: “如果存在关键字参数,则首先将其转换为位置参数,具体方式如下。首先,为形式参数创建未填充的槽列表。如果有N个位置参数,则它们被放置在前N个槽中。接下来,对于每个关键字参数,使用标识符确定相应的插槽(如果标识符与第一个形式参数名称相同,则使用第一个插槽,依此类推)。如果该插槽已经填充,则会引发TypeError异常。否则,参数的值将放置在插槽中,并填充它(即使表达式为None,也会填充插槽)。” https://docs.python.org/2/reference/expressions.html#calls

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接