为什么不能同时混合使用args和kwargs的关键字参数和非关键字参数?

8
在Python中,*args和**kwargs的用法对我来说很清楚,SO上有很多相关问题(例如Use of *args and **kwargsWhat does ** (double star/asterisk) and * (star/asterisk) do for parameters?)。
但是我想了解的一件事是:为什么不能同时定义强制位置参数,强制关键字参数,并最终允许像下面的一样捕获其他args和kwargs?
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, *, b, **kwargs):
    print(a, b)
    for key, value in kwargs.items():
        print(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, **kwargs):
    print(a, b)
    print(args)
    for key, value in kwargs.items():
        print(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, *args, **kwargs):
    print(a, b)
    print(args)
    print(kwargs)

可以在 could_do_this_but 函数的签名中省略 b,并在函数顶部执行(例如)kwargs.get("b", None),如果找到 None,则引发适当的错误...但是将 "b" 直接放在函数签名中将允许更快、更明确的代码开发,以便在将来调用该函数时使用。

1个回答

8

正确的语法是def cant_do_that(a, *args, b, **kwargs):。请注意,*仅使用一次,既用于标记位置参数的结束,又用于设置可变位置参数的名称。


函数定义中的*在位置或关键字参数和仅关键字参数之间的分隔符中具有语法上的独特性:

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

简而言之,语法"*"[参数]表示**args在语法上是相同的东西——一个字面上的*和可选名称——只能出现一次。使用裸体的*来开始仅接受关键字参数而不接受可变位置参数的形参,使用有名的*args来开始既接受关键字参数又接受可变位置参数的形参。

如果有表单“*标识符”,它将被初始化为一个元组,其中包含任何多余的位置参数,默认为空元组。[...] 在“*”或“*标识符”后面的参数是关键字-only 参数,并且只能使用关键字参数传递。


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