使用*args,**kwargs和optional/default参数调用Python函数

mgi*_*son 59 python syntax kwargs python-3.x

在python中,我可以定义一个函数如下:

def func(kw1=None,kw2=None,**kwargs):
   ...
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我可以调用func作为:

func(kw1=3,kw2=4,who_knows_if_this_will_be_used=7,more_kwargs=Ellipsis)
Run Code Online (Sandbox Code Playgroud)

我也可以定义一个函数:

def func(arg1,arg2,*args):
    ...
Run Code Online (Sandbox Code Playgroud)

可称为

func(3,4,additional,arguments,go,here,Ellipsis)
Run Code Online (Sandbox Code Playgroud)

最后,我可以将两种形式结合起来

def func(arg1,arg2,*args,**kwargs):
    ...
Run Code Online (Sandbox Code Playgroud)

但是,什么是行不通的是:

func(arg1,arg2,*args,kw1=None,kw2=None,**kwargs):  #SYNTAX ERROR (in python 2 only,  apparently this works in python 3)
    ...
Run Code Online (Sandbox Code Playgroud)

我最初的想法是,这可能是因为一个功能

def func(arg1,arg2,*args,kw1=None):
    ...
Run Code Online (Sandbox Code Playgroud)

可以称为

func(1,2,3) #kw1 will be assigned 3
Run Code Online (Sandbox Code Playgroud)

因此,这将引入一些含糊不清的关于3是否应该打包成args或kwargs.但是,使用python 3,可以指定仅关键字参数:

def func(a,b,*,kw=None):  #can be called as func(1,2), func(1,2,kw=3), but NOT func(1,2,3)
   ...
Run Code Online (Sandbox Code Playgroud)

有了这个,似乎没有语法模糊:

def func(a,b,*args,*,kw1=None,**kwargs):
    ...
Run Code Online (Sandbox Code Playgroud)

但是,这仍然会导致语法错误(使用Python3.2测试).这是否有理由让我失踪?并且,有没有办法获得我上面描述的行为(使用默认参数*args) - 我知道我可以通过操作函数内部的kwargs字典来模拟该行为.

agf*_*agf 60

可以在Python 3中做到这一点.

def func(a,b,*args,kw1=None,**kwargs):
Run Code Online (Sandbox Code Playgroud)

*仅当您想要指定仅关键字参数而不接受可变数量的位置参数时,才使用裸*args.你不要用两个*.

引用语法,在Python 2中,你有

parameter_list ::=  (defparameter ",")*
                    (  "*" identifier [, "**" identifier]
                    | "**" identifier
                    | defparameter [","] )
Run Code Online (Sandbox Code Playgroud)

而在Python 3中,你有

parameter_list ::=  (defparameter ",")*
                    (  "*" [parameter] ("," defparameter)*
                    [, "**" parameter]
                    | "**" parameter
                    | defparameter [","] )
Run Code Online (Sandbox Code Playgroud)

其中包括参数后的附加*参数.

更新:

这里有最新的Python 3文档.

  • @Nimi我专门展示了仅Python 3的功能,该功能允许您将命名参数放在* args后面,因此只能按名称使用它们,而不能使用位置。您所显示的内容允许按位置或名称填写“ kw1”-对于您的版本,“ func(1、2、3)”将填写“ a”,“ b”和“ kw1”,其中我的版本`func(1、2、3)`将填写`a`,`b`和`args`,并要求您执行`func(1、2,kw1 = 3)`在`kw1`中。 (2认同)

fra*_*ank 6

如果你想混合两者,记住*args和**kwargs必须是指定的最后一个参数.

def func(arg1,arg2,*args,kw1=None,kw2=None,**kwargs): #Invalid
def func(arg1,arg2,kw1=None,kw2=None,*args,**kwargs): #Valid
Run Code Online (Sandbox Code Playgroud)

这些注释似乎是基于混合函数定义的构造方式与所提供的参数如何分配回定义中指定的参数相比较.

这是该函数的定义,它有6个参数.它通过在函数调用中传递命名和未命名参数来调用.

对于此示例...在调用函数时命名参数时,可以不按顺序提供.arg1和arg2是必需参数,如果没有作为命名参数传递给函数,则必须从提供的未命名参数按顺序分配它们.kw1和kw2具有在函数定义中提供的默认值,因此它们不是必需的,但如果没有作为命名参数提供,它们将从剩余提供的未命名参数中获取任何可用值.剩下的任何未命名参数都被提供给名为args的数组中的函数.在函数定义中没有相应参数名的任何命名参数都被提供给名为kwargs的字典中的函数调用.

  • 这在语法上是有效的,但是不能像人们预期的那样工作,因为关于额外的必需参数是否映射到命名关键字参数或*args存在歧义. (7认同)
  • 我建议使用http://stackoverflow.com/a/15302038/527489 for Python 2.7并注意'def_val'. (3认同)
  • 我会更进一步说这不适用于使用Python 2.7制作kw1和kw2'关键字'args,这就是为什么我在这里!表单最好列为`func(arg1,arg2,arg3 = None,arg4 = None,*args,**kwargs):#Valid默认位置args`,但这实际上只是四个位置args,两个这是可选的.要传递kwargs,你需要填写*所有四个args*,包括arg3和arg4. (2认同)

Rom*_*man 5

清晰简洁:

Python 3.5或更高版本中:

def foo(a, b=3, *args, **kwargs):
  defaultKwargs = { 'c': 10, 'd': 12 }
  kwargs = { **defaultKwargs, **kwargs }
  
  print(a, b, args, kwargs)
  
  # Do something else

foo(1) # 1 3 () {'c': 10, 'd': 12}
foo(1, d=5) # 1 3 () {'c': 10, 'd': 5}
foo(1, 2, 4, d=5) # 1 2 (4,) {'c': 10, 'd': 5}
Run Code Online (Sandbox Code Playgroud)

注意:您可以在Python 2中使用

kwargs = merge_two_dicts(defaultKwargs, kwargs)
Run Code Online (Sandbox Code Playgroud)

Python 3.5中

kwargs = { **defaultKwargs, **kwargs }
Run Code Online (Sandbox Code Playgroud)

Python 3.9中

kwargs = defaultKwargs | kwargs  # NOTE: 3.9+ ONLY
Run Code Online (Sandbox Code Playgroud)