为什么Python允许关键字参数后的*args?

2024-05-19 00:07:08 发布

您现在位置:Python中文网/ 问答频道 /正文

示例:

def foo(a, b=2, *args, **kwargs): pass

为什么这不会导致语法错误?*args不会捕获其他非关键字参数,因为在关键字参数之后传递它们是非法的。你知道吗

对于python3.x,*args、**kwargs的正确用法在本例中如下所示:

def foo(a, *args, b=2, **kwargs): pass

谢谢你对这种奇怪行为的任何见解。你知道吗

编辑:

感谢Jab把我引向pep3102,它简明地解释了这种行为。过来看!你知道吗

同时也要感谢jsbueno的额外出色解释,由于它的彻底性,我将其更新为最佳答案。你知道吗


Tags: 编辑示例用法参数foodefargspass
2条回答

由于多种原因,它被实现到3.X中。最好的回答方法是参考
PEP 3102

还可以查看python3.0.1文档中的New Syntax部分。你知道吗

TLDR:

Named parameters occurring after *args in the parameter list must be specified using keyword syntax in the call. You can also use a bare * in the parameter list to indicate that you don’t accept a variable-length argument list, but you do have keyword-only arguments.

给出:

def foo(a, b=2, *args, **kwargs): pass

b不是一个只包含关键字的参数-它只是一个参数,参数可以是位置的或命名的,但是有一个默认值。不可能将任何值传递到args中,并且在建议的签名中忽略按顺序传递b或传递b。你知道吗

这个签名是有意义的,而且非常明确-可以传递0到n个位置参数,但是如果传递2个或更多,则第二个参数将被分配给“b”,故事结束。 如果传递0个位置参数,仍然可以将值作为命名参数赋给“a”或“b”,但尝试类似于:foo(0, 1, 2, a=3, b=4)的操作将失败,因为尝试将多个值传递给两个参数。你知道吗

其中:

def foo(a, *args, b=2, **kwargs): pass

这也是一种明确的情况:第一个位置参数指向“a”,其他参数指向“args”,您只能将一个值作为命名参数传递给“b”。你知道吗

python3.8附带的签名定义中新的/语法为这一点提供了更大的灵活性,允许要求将“a”和“b”作为仅位置参数传递。同样,没有含糊不清的地方:

def foo(a, b=2, /, *args, **kwargs): pass

这种新语法有一个奇怪的地方:一个是允许将命名参数传递给“A”和“b”,但命名参数将作为键/值对出现在“kwargs”中,而局部变量“A”和“b”将被分配仅位置参数:

def foo(a, b=2, /, *args, **kwargs): 
    print(a, b, args, kwargs)

...

In [9]: foo(1, 2, a=3, b=4)                                                                                                                                               
1 2 () {'a': 3, 'b': 4}

而对于传统语法,您询问-def foo(a, b=2, *args, **kwargs):-如果尝试了,就会得到一个TypeError:

In [11]: foo(1,2, a=3, b=4)                                                                                                                                               
                                     -
TypeError                                 Traceback (most recent call last)
<ipython-input-11-d002c7717dba> in <module>
  > 1 foo(1,2, a=3, b=4)

TypeError: foo() got multiple values for argument 'a'

相关问题 更多 >

    热门问题