Почему аргументы не по умолчанию не следуют за аргументами по умолчанию?

139

Почему этот кусок кода генерирует ошибку SyntaxError?

  >>> def fun1(a="who is you", b="True", x, y):
...     print a,b,x,y
... 
  File "<stdin>", line 1
SyntaxError: non-default argument follows default argument

Пока следующий кусок кода работает без видимых ошибок:

>>> def fun1(x, y, a="who is you", b="True"):
...     print a,b,x,y
... 
dotslash
источник
в Python это как структура, когда вы определяете функцию def myfunction(position_arguments, *arguments, **keywords):`....`
abhishekgarg

Ответы:

173

Все обязательные параметры должны быть помещены перед аргументами по умолчанию. Просто потому, что они обязательны, а аргументы по умолчанию - нет. Синтаксически, для интерпретатора было бы невозможно решить, какие значения соответствуют каким аргументам, если разрешены смешанные режимы. A SyntaxErrorвызывается, если аргументы указаны не в правильном порядке:

Давайте посмотрим на ключевые аргументы, используя вашу функцию.

def fun1(a="who is you", b="True", x, y):
...     print a,b,x,y

Предположим, что разрешено объявлять функцию, как указано выше. Затем с помощью описанных выше объявлений мы можем сделать следующие (обычные) позиционные вызовы или вызовы аргументов с ключевыми словами:

func1("ok a", "ok b", 1)  # Is 1 assigned to x or ?
func1(1)                  # Is 1 assigned to a or ?
func1(1, 2)               # ?

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

>>> def fun1(x, y, a="who is you", b="True"):
...     print a,b,x,y
... 

Ссылка O'Reilly - Core-Python
Где в этой функции используются аргументы по умолчанию, синтаксически правильные для приведенных выше вызовов функций. Вызов аргументов по ключевым словам оказывается полезным для обеспечения возможности позиционных аргументов не по порядку, но в сочетании с аргументами по умолчанию их также можно использовать для «пропуска» пропущенных аргументов.

Рахул Гаутам
источник
4
<q> Синтаксически, для интерпретатора было бы невозможно решить, какие значения соответствуют каким аргументам, если разрешены смешанные режимы. </ q> Ruby допускает аргументы не по умолчанию после аргументов по умолчанию. <q> Как вы будете предлагать присваивание переменных при вызове функции </ q> Просто используйте func1(x=1, y=2).
слабое
Привет, @weakish, спасибо за комментарий, у Python есть хороший способ добиться этого, пожалуйста, поищи * args и ** kwargs
Rahul Gautam
Привет @Rahul Gautam Я в замешательстве. Я думал, **kwargsне может сделать def fun1(a="who is you", b="True", x, y)или подобную работу. Если вы используете def f(**kwargs), вам нужно обрабатывать значения по умолчанию в теле?
слабое
@ Слабое def fun1(a="who is you", b="True", x, y)то же самое можно достичь с другим стилем. если def fun1 (** kwrgs) `, то вызывать fun1({'a': 'who is you', 'b': True})нет необходимости передавать x и y.
Рахул Гаутам
2
Почему вы пишете «Синтаксически, для интерпретатора было бы невозможно решить, какие значения соответствуют каким аргументам, если разрешены смешанные режимы».? Я думаю, что алгоритм на PEP 3102 мог бы работать точно так же, даже если def foo(x=None, y)бы это было разрешено. Поэтому мне все еще интересно, почему это не разрешено Python. Есть ли настоящая фундаментальная причина или это просто «мы не разрешаем это, потому что мы не разрешаем это».
Йерун Демейер
15
SyntaxError: non-default argument follows default argument

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

В Python 3, однако, вы можете сделать следующее:

def fun1(a="who is you", b="True", *, x, y):
    pass

который делает xи yтолько ключевое слово, так что вы можете сделать это:

fun1(x=2, y=2)

Это работает, потому что больше нет двусмысленности. Обратите внимание, что вы все еще не можете сделать fun1(2, 2)(это установит аргументы по умолчанию).

jamylak
источник
Аргументы только для ключевого слова - отличная особенность Python 3. Жаль, что патч для их переноса на Python 2.6 и 2.7 просто остался в силе .
Ник Чаммас,
10

Позвольте мне прояснить два момента здесь:

  • во-первых, аргумент не по умолчанию не должен следовать за аргументом по умолчанию, это означает, что вы не можете определить (a = b, c) в функции, порядок определения параметра в функции:
    • позиционный параметр или нестандартный параметр т.е. (a, b, c)
    • параметр ключевого слова или параметр по умолчанию, т. е. (a = "b", r = "j")
    • параметр только для ключевых слов т.е. (* args)
    • параметр ключевого слова var т.е. (** kwargs)

def example(a, b, c=None, r="w" , d=[], *ae, **ab):

(а, б) - позиционный параметр

(c = none) является необязательным параметром

(r = "w") является ключевым параметром

(d = []) является параметром списка

(* ae) только для ключевых слов

(** ab) - параметр ключевого слова var

  • Теперь второстепенная вещь, если я попробую что-то вроде этого: def example(a, b, c=a,d=b):

аргумент не определен при сохранении значений по умолчанию, Python вычисляет и сохраняет значения по умолчанию при определении функции

c и d не определены, не существует, когда это происходит (существует только при выполнении функции)

"a, a = b" не допускается в параметре.

Аадитя Ура
источник
0

Обязательные аргументы (без значений по умолчанию) должны быть в начале, чтобы клиентский код мог указывать только два. Если бы необязательные аргументы были в начале, это могло бы сбить с толку:

fun1("who is who", 3, "jack")

Что бы это сделать в вашем первом примере? В последнем случае x - это «кто есть кто», y равно 3 и a = «валет».

cforbish
источник