Чому аргументи за замовчуванням не можуть слідувати аргументами за замовчуванням?


138

Чому цей фрагмент коду кидає 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
... 

у python це така структура, коли ви визначаєте функцію def myfunction(position_arguments, *arguments, **keywords):`....`
abhishekgarg

Відповіді:


172

Усі необхідні параметри повинні бути розміщені перед будь-якими аргументами за замовчуванням. Просто тому, що вони є обов'язковими, тоді як аргументи за замовчуванням - ні. Синтаксично інтерпретатору було б неможливо вирішити, які значення відповідають аргументам, якщо дозволено змішані режими. 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), вам потрібно обробляти значення за замовчуванням в тілі?
слабкий

@weakish def fun1(a="who is you", b="True", x, y)те ж саме можна досягти іншим стилем. якщо def fun1 (** kwrgs) `, тоді виклику fun1({'a': 'who is you', 'b': True})немає потреби передавати х і у.
Рахул Гаутам

2
Чому ви пишете "Синтаксично, перекладач не міг вирішити, які значення відповідають яким аргументам, якщо дозволені змішані режими". Я думаю, що алгоритм на PEP 3102 міг би працювати точно так само, навіть якщо це def foo(x=None, y)було б дозволено. Тож мені все ще цікаво, чому Python цього не дозволяє. Чи є реальна фундаментальна причина чи це просто "ми не дозволяємо цього, тому що не дозволяємо".
Jeroen Demeyer

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)(це встановило б аргументи за замовчуванням).


Аргументи, що стосуються лише ключових слів, є чіткою особливістю 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):

(a, b) - позиційний параметр

(c = немає) - необов'язковий параметр

(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 = "джек".

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.