函数参数中仅带有星号?


240

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

当我查看pickle模块时,我看到了:

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。


Answers:


220

Bare *用于强制调用者使用命名参数-因此,如果*没有以下关键字参数,则无法将函数定义为参数。

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


3
请注意,所有位置(未命名)参数(包括在内*args)都必须在裸机之前出现*
BallpointBenpoint,2015年

4
还要注意,还有一个对应的/标记了仅位置参数的结尾(stackoverflow.com/questions/28243832/…)。
斯蒂芬

2
@BallpointBen:*代替*args,反之亦然;它们不能共存于签名中。这就是为什么他们选择*;以前,这*args是强制使用纯位置参数的唯一方法,并且它标记了可以在位置上传递的参数的结尾(由于它收集了所有其余的位置参数,因此可以到达以下命名的参数)。*表示相同的“位置参数不能超出此处”,但是缺少名称意味着“但我根本不会接受它们,因为我选择不提供放置它们的位置”。
ShadowRanger

70

当原始答案完全回答问题时,只需添加一些相关信息即可。单个星号的行为源自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"


哦,这使事情更加清楚了。所以实际上拥有一个参数*就像拥有一个参数args *一样,但是由于您没有给它命名,它的唯一作用可能是悄悄地吞噬所有其余的位置参数,以强制将其余的参数设为关键字-只要。
斯蒂芬

11
@Stephen我本来也以为,裸露的作用*是吞噬剩余的位置参数,但事实并非如此。传递超出函数预期的位置参数,将产生此类错误:foo() takes exactly 1 positional argument (2 given)
Ajay M,

18
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'}

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

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

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


4

假设您具有以下功能:

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

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

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

假设您只想sum使用关键字参数来调用函数。

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

所以函数定义为:

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

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


-1

我发现下面的链接,是非常有益的解释**args以及**kwargs

https://pythontips.com/2013/08/04/args-and-kwargs-in-python-explained/

本质上,除了上面的答案之外,我还从上面的网站(信用:https : //pythontips.com/author/yasoob008/)学到了以下内容:

在下面首先定义演示功能的情况下,有两个示例,一个带有*args和一个带有**kwargs

def test_args_kwargs(arg1, arg2, arg3):
    print "arg1:", arg1
    print "arg2:", arg2
    print "arg3:", arg3

# first with *args
>>> args = ("two", 3,5)
>>> test_args_kwargs(*args)
arg1: two
arg2: 3
arg3: 5

# now with **kwargs:
>>> kwargs = {"arg3": 3, "arg2": "two","arg1":5}
>>> test_args_kwargs(**kwargs)
arg1: 5
arg2: two
arg3: 3

因此*args,您可以动态建立一个参数列表,该参数列表将按照其输入的顺序进行处理,而**kwargs可以启用NAMED参数的传递,并且可以由NAME进行相应的处理(而与它们的输入顺序无关) 。

该站点继续,并指出参数的正确顺序应为:

some_func(fargs,*args,**kwargs)

2
这个答案几乎与问题无关。它甚至使用了不具备该功能的过时的python版本。
Antti Haapala
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.