Bare asterisk in function arguments?

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


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.


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.


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