函数参数中仅带有星号?

问题:函数参数中仅带有星号?

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

当我查看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。

What does a bare asterisk in the arguments of a function do?

When I looked at the pickle module, I see this:

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

I know about a single and double asterisks preceding arguments (for variable number of arguments), but this precedes nothing. And I’m pretty sure this has nothing to do with pickle. That’s probably just an example of this happening. I only learned its name when I sent this to the interpreter:

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

If it matters, I’m on python 3.3.0.


回答 0

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

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

Bare * is used to force the caller to use named arguments – so you cannot define a function with * as an argument when you have no following keyword arguments.

See this answer or Python 3 documentation for more details.


回答 1

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

While the original answer answers the question completely, just adding a bit of related information. The behaviour for the single asterisk derives from PEP-3102. Quoting the related section:

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):
        ...

In simple english, it means that to pass the value for key, you will need to explicitly pass it as key="value".


回答 2

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

the above example with **kwargs

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

func(a="aa",b="bb", c="cc") # aa, bb, {'c': 'cc'}

回答 3

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

>>> 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开发人员选择让您以前一种方式编写它。

Semantically, it means the arguments following it are keyword-only, so you will get an error if you try to provide an argument without specifying its name. For example:

>>> 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

Pragmatically, it means you have to call the function with a keyword argument. It’s usually done when it would be hard to understand the purpose of the argument without the hint given by the argument’s name.

Compare e.g. sorted(nums, reverse=True) vs. if you wrote sorted(nums, True). The latter would be much less readable, so the Python developers chose to make you to write it the former way.


回答 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)

Suppose you have function:

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

You can call this function in 2 ways:

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

Suppose you want function sum to be called only using keyword arguments.

You add * to the function parameter list to mark the end of positional arguments.

So function defined as:

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

may be called only using sum(1,key=2)


回答 5

我发现下面的链接,是非常有益的解释**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)

I’ve found the following link to be very helpful explaining *, *args and **kwargs:

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

Essentially, in addition to the answers above, I’ve learned from the site above (credit: https://pythontips.com/author/yasoob008/) the following:

With the demonstration function defined first below, there are two examples, one with *args and one with **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

So *args allows you to dynamically build a list of arguments that will be taken in the order in which they are fed, whereas **kwargs can enable the passing of NAMED arguments, and can be processed by NAME accordingly (irrespective of the order in which they are fed).

The site continues, noting that the correct ordering of arguments should be:

some_func(fargs,*args,**kwargs)