Голая звездочка в аргументах функции?

Что делает голая звездочка в аргументах функции?

Когда я посмотрел на модуль рассола, я увидел это:

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.

Ответ 1

Bare * используется, чтобы заставить вызывающего пользователя использовать именованные аргументы - поэтому вы не можете определить функцию с * в качестве аргумента, если у вас нет следующих аргументов ключевого слова.

Подробнее см. этот ответ или документацию Python 3.

Ответ 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="value".

Ответ 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'}

Ответ 4

Я нашел очень полезной следующую ссылку, объясняющую *, *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 может **kwargs передачу аргументов NAMED и может обрабатываться NAME соответственно (независимо от порядка в которым их кормят).

Сайт продолжает, отмечая, что правильный порядок аргументов должен быть:

some_func(fargs,*args,**kwargs)