Позиционный аргумент после ключевого аргумента и обычный параметр после * параметра - PullRequest
1 голос
/ 07 января 2020

Мне нужно использовать Python 2.7, и я сталкиваюсь с проблемой, которой у меня не было в Python 3.

def foo(*dirs, arg2, arg3=None, arg4=None, arg5=False, arg6=False):

Я бы вызвал функцию так:

foo('folder_name', arg2=100, arg3=['string', 'string2'], arg4='test6', arg5=True, arg6=False)

Но я получаю сообщение об ошибке:

                     def foo(*dirs, arg2, arg3=None, arg4=None, arg5=False, arg6=False):
                                       ^
SyntaxError: invalid syntax

В определении функции, которое я вижу, написано regular parameter after * parameter. Я провел некоторое исследование и вижу, что *dirs должен быть последним указанным параметром.

Так что я могу изменить параметры функции следующим образом:

def foo(arg2, arg3=None, arg4=None, arg5=False, arg6=False, *dirs):

Однако, когда я делаю это, я затем получите сообщение об ошибке: SyntaxError: non-keyword arg after keyword arg

Я не уверен, как решить эту проблему. Кто-нибудь знает способ решить эту проблему? Любая помощь приветствуется!

Ответы [ 2 ]

1 голос
/ 07 января 2020

Если параметр dirs указывает один аргумент (позиционный или ключевое слово) для foo, например, одна строка или одна список строк, в Другими словами, если вы намереваетесь назвать foo, например:

foo("folder_name", other args)

или

foo(["folder_name1", "folder_name2, ...], other args)

, тогда вам не нужно ставить его имя перед * и "обходной путь" вашего ответа на самом деле путь к go. См. Также: https://docs.python.org/2/tutorial/controlflow.html#more -on-defining-functions .

Но если dirs указывает произвольную последовательность аргументов, и вы хотите иметь возможность делать что-то вроде:

foo(other args, "folder_name1", "folder_name2",...)

есть разница между python 2 и python 3, как вы описываете в своем вопросе. Как вы можете видеть https://docs.python.org/2/glossary.html#term -параметр против https://docs.python.org/3/glossary.html#term -параметр , в Python3 есть только для ключевых слов параметры:

Параметры только для ключевых слов могут быть определены путем включения одного параметра var-positional или bare * в список параметров определения функции перед ними

Именно поэтому в Python3 вы не сделали не может быть определено foo как:

def foo(*dirs, arg2, arg3=None, arg4=None, arg5=False, arg6=False):

и названо так:

foo('folder_name', arg2=100, arg3=['string', 'string2'], arg4='test6', arg5=True, arg6=False)

Обратите внимание, что в вызове вы правильно указали все аргументы после "folder_name" (даже * 1047) *) в качестве аргументов ключевых слов и т. д. работали в Python3.

Но в Python2 нет параметров только для ключевых слов. Итак, как вы упоминаете, вы не можете иметь ни regular parameter after * parameter, ни non-keyword arg after keyword arg. Вот почему, даже если вы оставите *dirs последним в списке параметров, вы не сможете вызвать foo, предоставив предыдущие аргументы в качестве ключевых. Однако вы можете оставить *dirs последним в списке параметров, а при вызове foo предоставить предыдущие аргументы как позиционные. Пример (python 2.7):

def bar(a=1, b=2, *c):   # see below
    return (a, b, c)
bar(1, 2, 3)      # => (1, 2, (3,))
bar(1, b=3, 3)    # => Error: non-keyword arg after keyword arg
bar(1, 2)         # => (1 2 ())
bar(1)            # => Error: bar() takes at least 2 arguments (1 given)

Итак, как вы можете видеть, даже если он позволяет определить панель со значениями по умолчанию для a, b (см. positional-or-keyword * 1060) * в ссылках выше), они не используются, то есть a и b являются позиционными (и обязательными).

Наконец, также проверьте эти ссылки из python2 документации: https://docs.python.org/2/tutorial/controlflow.html#unpacking -argument-lists и https://docs.python.org/2/faq/programming.html#what - это разница между аргументами и параметрами

1 голос
/ 07 января 2020

Я нашел обходной путь, но я открыт для других идей, если у кого-то есть.

Я изменил *dirs в определении функции на аргумент ключевого слова dirs=None, тогда когда я вызываю foo(dirs='folder_name', other arguments), работает хорошо.

...