裸星号在参数列表中有什么作用?什么是“仅关键字”参数?

What does a bare asterisk do in a parameter list? What are "keyword-only" parameters?

提问人:Eric 提问时间:1/13/2013 最后编辑:Trenton McKinneyEric 更新时间:9/5/2023 访问量:95536

问:

函数参数中的裸星号有什么作用?

当我查看泡菜模块时,我看到了这一点:

pickle.dump(obj, file, protocol=None, *, fix_imports=True)

我知道参数前面有一个单星号和双星号(用于可变数量的参数),但这之前什么都没有。我很确定这与泡菜无关。这可能只是这种情况的一个例子。当我把这个发给口译员时,我才知道它的名字:

>>> def func(*):
...     pass
...
  File "<stdin>", line 1
SyntaxError: named arguments must follow bare *

如果重要的话,我在python 3.3.0上。

python-3.x 传递 关键字参数位置 参数

评论

12赞 Tom Hale 6/9/2019
相关: Python 函数定义中的裸正斜杠?
0赞 Charlie Parker 10/30/2021
有关代码示例的说明,请参阅:stackoverflow.com/a/14298976/1601580

答:

425赞 Kimvais 1/13/2013 #1

Bare 用于强制调用方使用命名参数 - 因此,当您没有以下关键字参数时,您不能定义一个函数作为参数。**

有关更多详细信息,请参阅此答案Python 3 文档

评论

0赞 Charlie Parker 10/30/2021
有关代码示例的说明,请参阅:stackoverflow.com/a/14298976/1601580
1赞 ado sar 4/2/2023
但是为什么会返回相同的语法错误呢?def foo(a, *, **kwargs)
0赞 outa 4/18/2023
@ado sar:有意思。我刚刚在上面找到了这个讨论: bugs.python.org/issue2613
120赞 Anshul Goyal 9/2/2016 #2

虽然原始答案完全回答了问题,但只是添加了一些相关信息。单个星号的行为源自 PEP-3102。引用相关部分:

The second syntactical change is to allow the argument name to
be omitted for a varargs argument. The meaning of this is to
allow for keyword-only arguments for functions that would not
otherwise take a varargs argument:

    def compare(a, b, *, key=None):
        ...

在简单的英语中,这意味着要传递 key 的值,您需要显式地将其传递为 .key="value"

评论

5赞 Stephen 4/26/2018
哦,这让事情变得更加清晰。因此,实际上有一个参数 * 就像一个参数 args*,但由于您没有给它命名任何东西,它的唯一效果可能是悄悄地吞噬所有剩余的位置参数,以强制剩余的参数仅包含关键字。
18赞 Ajay M 5/27/2018
@Stephen我最初也认为,裸露的效果是吞噬剩余的立场论点,但事实并非如此。传递比函数预期的额外的位置参数,会产生此类错误:*foo() takes exactly 1 positional argument (2 given)
0赞 Horror Vacui 8/31/2020
我会在“作为一个方便的快捷方式,我们可以简单地省略'忽略'名称,意思是'不允许任何超过这一点的位置参数'”之前添加 PEP 示例。这个等效的例子清楚地表明了它的作用。
73赞 laycat 10/23/2018 #3
def func(*, a, b):
    print(a)
    print(b)

func("gg") # TypeError: func() takes 0 positional arguments but 1 was given
func(a="gg") # TypeError: func() missing 1 required keyword-only argument: 'b'
func(a="aa", b="bb", c="cc") # TypeError: func() got an unexpected keyword argument 'c'
func(a="aa", b="bb", "cc") # SyntaxError: positional argument follows keyword argument
func(a="aa", b="bb") # aa, bb

上面的例子是 **kwargs

def func(*, a, b, **kwargs):
    print(a)
    print(b)
    print(kwargs)

func(a="aa",b="bb", c="cc") # aa, bb, {'c': 'cc'}
30赞 rok 11/1/2019 #4

假设你有函数:

def sum(a,key=5):
    return a + key 

可以通过 2 种方式调用此函数:

sum(1,2)sum(1,key=2)

假设您希望仅使用关键字参数调用函数。sum

添加到函数参数列表中以标记位置参数的末尾。*

所以函数定义为:

def sum(a,*,key=5):
    return a + key 

只能使用sum(1,key=2)

69赞 kaya3 11/25/2019 #5

从语义上讲,这意味着它后面的参数是纯关键字的,因此,如果您尝试提供参数而不指定其名称,则会出现错误。例如:

>>> def f(a, *, b):
...     return a + b
...
>>> f(1, 2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() takes 1 positional argument but 2 were given
>>> f(1, b=2)
3

实际上,这意味着您必须使用关键字参数调用函数。如果没有参数名称给出的提示,则很难理解参数的目的时,通常会这样做。

比较例如 vs. 如果你写了.后者的可读性要低得多,因此 Python 开发人员选择让你以前一种方式编写它。sorted(nums, reverse=True)sorted(nums, True)