为什么不能仅将args和仅关键字参数同时与* args和** kwargs混合

问题描述

我很清楚在Python中使用* args和** kwargs的情况,因此在SO中有很多问题(例如Use of *args and **kwargsWhat does ** (double star/asterisk) and * (star/asterisk) do for parameters?)。

但是我想了解的一件事是:为什么不可能同时定义强制性的位置args,强制性的kwarg参数,并最终仍然允许捕获其他args和kwargs,如下面的cant_do_that一样?

def one_kwarg_is_mandatory(*,b,**kwargs):
    print(b)
    for key,value in kwargs.items():
        print(key,value)    
        
def one_pos_arg_and_one_kwarg_are_mandatory(a,*,**kwargs):
    print(a,b)
    for key,value)
      
# I wanted a mandatory arg (a) and possibly parse other args (*args),# then a mandatory kwarg (b) and eventually other kwargs (**kwargs)
def cant_do_that(a,*args,b)
    print(args)
    for key,value)

# not really interested on this because "b" must be a kwarg and hiding 
# it under **kwargs would not be explicit enough for my customer (sometimes myself ;))
def Could_do_this_but(a,b)
    print(args)
    print(kwargs)

是的,可以摆脱b函数签名中的Could_do_this_but,在函数顶部执行(例如)kwargs.get("b",None)并在发现{{ 1}} ......但是直接在函数签名上使用“ b”将允许使用该函数进行更快,更明确的代码开发。

解决方法

正确的语法是def cant_do_that(a,*args,b,**kwargs):。请注意,*仅使用一次,两者都用于标记位置参数的结尾,并且来设置可变位置参数的名称。


function definition is syntactically unique中的*,位于位置或关键字参数与仅关键字参数之间:

parameter_list_starargs   ::=  "*" [parameter] ("," defparameter)* ["," ["**" parameter [","]]]
                               | "**" parameter [","]

简而言之,语法"*" [parameter]意味着**args在语法上是同一个东西–文字*和可选名称–只能出现一次。使用裸露的*来启动纯关键字参数而没有接受可变参数的位置参数,并使用命名为*args来启动纯关键字参数 with 接受可变参数的位置论证。

如果存在形式“ *identifier”,则将其初始化为元组 接收任何多余的位置参数,默认为空 元组。 [...]“ *”或“ *identifier”之后的参数仅是关键字 参数,并且只能使用关键字参数传递。