Подтвердить что ты не робот

Какова цель голой астерикс в аргументах функции?

Я видел этот SO-вопрос (это не дубликат): Python голая звездочка в аргументе функции

В python-3.x вы можете добавить аргумент функции * в аргументы функции, это означает, что (цитата из docs):

Параметры после "*" или "* идентификатор" являются параметрами только для ключевого слова и могут передаваться только аргументы ключевого слова.

Итак, я определил функцию:

>>> def f(a, b, *, c=1, d=2, e=3):
...     print('Hello, world!')
... 

Я могу передавать значения c, d и e только путем указания ключевых слов:

>>> f(1, 2, 10, 20, 30)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() takes 2 positional arguments but 5 were given
>>> f(1, 2, c=10, d=20, e=30)
Hello, world!

Вопросы:

  • Какова мотивация такого типа ограничения/синтаксиса сахара?
  • В каких случаях он распространяется?
  • Действительно ли он используется в сторонних библиотеках, которые переключаются на python3?

Некоторые примеры "реального мира" очень помогли бы. Спасибо заранее.

4b9b3361

Ответ 1

PEP 3102 объясняет это довольно ясно: задача состоит в том, чтобы позволить функциям принимать различные "варианты", которые по сути являются ортогональными по своей природе. Указание этих позиций неудобно как на определяющей, так и на вызывающей стороне, поскольку у них нет никакого очевидного "приоритета", который переводится в позиционный порядок.

Есть много примеров функций, которые могли бы извлечь выгоду из этого в различных библиотеках. Например, сигнатура вызова pandas.read_csv:

def parser_f(filepath_or_buffer,
                 sep=sep,
                 dialect=None,
                 compression=None,

                 doublequote=True,
                 escapechar=None,
                 quotechar='"',
                 quoting=csv.QUOTE_MINIMAL,
                 skipinitialspace=False,
                 lineterminator=None,

                 header='infer',
                 index_col=None,
                 names=None,
                 prefix=None,
                 skiprows=None,
                 skipfooter=None,
                 skip_footer=0,
                 na_values=None,
                 na_fvalues=None,
                 true_values=None,
                 false_values=None,
                 delimiter=None,
                 converters=None,
                 dtype=None,
                 usecols=None,

                 engine='c',
                 delim_whitespace=False,
                 as_recarray=False,
                 na_filter=True,
                 compact_ints=False,
                 use_unsigned=False,
                 low_memory=_c_parser_defaults['low_memory'],
                 buffer_lines=None,
                 warn_bad_lines=True,
                 error_bad_lines=True,

                 keep_default_na=True,
                 thousands=None,
                 comment=None,
                 decimal=b'.',

                 parse_dates=False,
                 keep_date_col=False,
                 dayfirst=False,
                 date_parser=None,

                 memory_map=False,
                 nrows=None,
                 iterator=False,
                 chunksize=None,

                 verbose=False,
                 encoding=None,
                 squeeze=False,
                 mangle_dupe_cols=True,
                 tupleize_cols=False,
                 infer_datetime_format=False):

За исключением пути к файлу, большинство из них являются ортогональными опциями, которые определяют различные аспекты того, как должен анализироваться файл CSV. Нет особых причин, по которым они будут переданы в каком-либо конкретном порядке. Вы бы сходите с ума, отслеживая любой позиционный порядок для них. Имеет смысл передавать их как ключевые слова.

Теперь вы можете видеть, что pandas на самом деле не определяет их как аргументы только для ключевого слова, предположительно для поддержания совместимости с Python 2. Я бы предположил, что многие библиотеки воздерживались от использования синтаксиса по той же причине. Я не знаю, из каких библиотек (если они есть) начали использовать его.

Ответ 2

Для тех, кто приходит или используется ruby

Ниже выражение в python

def f(a, b, *, c=1, d=2, e=3):

похож на

def f(a,b, options={})
  c = options[:c] || 1
  d = options[:d] || 2
  e = options[:e] || 3
end

в рубине.

Так как python явный лучше, чем неявный, он требует * (splat) оператор в параметрах.

PS: Я никогда не использовал python, если я ошибаюсь, пожалуйста, исправьте меня.