Dlaczego argumenty inne niż domyślne nie mogą występować po argumentach domyślnych?

137

Dlaczego ten fragment kodu generuje błąd 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

Podczas gdy następujący fragment kodu działa bez widocznych błędów:

>>> def fun1(x, y, a="who is you", b="True"):
...     print a,b,x,y
... 
dotslash
źródło
w Pythonie taka jest struktura podczas definiowania funkcji def myfunction(position_arguments, *arguments, **keywords):`....`
abhishekgarg

Odpowiedzi:

172

Wszystkie wymagane parametry należy umieścić przed wszelkimi domyślnymi argumentami. Po prostu dlatego, że są obowiązkowe, podczas gdy domyślne argumenty nie. Składniowo interpretator nie byłby w stanie zdecydować, które wartości pasują do których argumentów, gdyby tryby mieszane były dozwolone. A SyntaxErrorjest podnoszone, jeśli argumenty nie są podane we właściwej kolejności:

Przyjrzyjmy się argumentom słów kluczowych, używając Twojej funkcji.

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

Załóżmy, że można zadeklarować funkcję jak powyżej.Następnie za pomocą powyższych deklaracji możemy wykonać następujące (zwykłe) wywołania argumentów pozycyjnych lub słów kluczowych:

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

Jak zasugerujesz przypisanie zmiennych w wywołaniu funkcji, jak będą używane domyślne argumenty wraz z argumentami słów kluczowych.

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

Odniesienie O'Reilly - Core-Python
Gdzie ta funkcja wykorzystuje domyślne argumenty poprawne składniowo dla powyższych wywołań funkcji. Wywoływanie argumentów słów kluczowych okazuje się przydatne, ponieważ umożliwia dostarczenie argumentów pozycyjnych spoza kolejności, ale w połączeniu z argumentami domyślnymi można ich również używać do „przeskakiwania” brakujących argumentów.

Rahul Gautam
źródło
3
<q> Składniowo interpreter nie byłby w stanie zdecydować, które wartości pasują do których argumentów, gdyby tryby mieszane były dozwolone. </q> Ruby dopuszcza argumenty inne niż domyślne po domyślnych. <q> Jak zasugerujesz przypisanie zmiennych w wywołaniu funkcji </q> Po prostu użyj func1(x=1, y=2).
słabe
Cześć @weakish, dzięki za komentarz, Python ma piękny sposób, aby osiągnąć to, proszę iść szukać * args i ** kwargs
Rahul gautam
Cześć @Rahul Gautam, jestem zdezorientowany. Myślałem, że **kwargsnie mogę wykonać def fun1(a="who is you", b="True", x, y)ani podobnej pracy. Jeśli używasz def f(**kwargs), musisz obsługiwać domyślne wartości w treści?
słaby
@ słabe def fun1(a="who is you", b="True", x, y)to samo można osiągnąć, stosując inny styl. if def fun1 (** kwrgs) `wtedy wywołanie fun1({'a': 'who is you', 'b': True})nie ma potrzeby przekazywania x i y.
Rahul Gautam,
1
Dlaczego piszesz „Składniowo byłoby niemożliwe, aby interpreter zdecydował, które wartości pasują do których argumentów, gdyby tryby mieszane były dozwolone”? Myślę, że algorytm w PEP 3102 mógłby działać dokładnie tak samo, nawet gdyby def foo(x=None, y)był dozwolony. Więc nadal jestem ciekawy, dlaczego Python nie pozwala na to. Czy istnieje prawdziwy fundamentalny powód, czy jest to po prostu „nie pozwalamy na to, ponieważ na to nie pozwalamy”.
Jeroen Demeyer
15
SyntaxError: non-default argument follows default argument

Jeśli pozwolisz na to, domyślne argumenty staną się bezużyteczne, ponieważ nigdy nie będziesz w stanie użyć ich wartości domyślnych, ponieważ argumenty inne niż domyślne pojawiają się po .

Jednak w Pythonie 3 możesz wykonać następujące czynności:

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

co sprawia, że xi ysłowo kluczowe tylko po to, abyś mógł to zrobić:

fun1(x=2, y=2)

To działa, ponieważ nie ma już żadnej dwuznaczności. Zauważ, że nadal nie możesz tego zrobić fun1(2, 2)(to ustawiłoby domyślne argumenty).

jamylak
źródło
Argumenty zawierające tylko słowa kluczowe są fajną cechą Pythona 3. Szkoda, że ​​łatka przenosząca je do Pythona 2.6 i 2.7 właśnie wygasła .
Nick Chammas
10

Pozwólcie, że wyjaśnię tutaj dwie kwestie:

  • po pierwsze argument inny niż domyślny nie powinien następować po argumencie domyślnym, oznacza to, że nie można zdefiniować (a = b, c) w funkcji kolejności definiowania parametrów w funkcji:
    • parametr pozycyjny lub parametr inny niż domyślny, tj. (a, b, c)
    • parametr słowa kluczowego lub parametr domyślny, tj. (a = "b", r = "j")
    • parametr zawierający tylko słowo kluczowe, tj. (* args)
    • parametr słowa kluczowego var, tj. (** kwargs)

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

(a, b) są parametrami pozycyjnymi

(c = none) jest parametrem opcjonalnym

(r = "w") to parametr słowa kluczowego

(d = []) to parametr listy

(* ae) dotyczy tylko słów kluczowych

(** ab) jest parametrem słowa kluczowego var

  • teraz drugorzędną rzeczą jest, jeśli spróbuję czegoś takiego: def example(a, b, c=a,d=b):

argument nie jest zdefiniowany podczas zapisywania wartości domyślnych, Python oblicza i zapisuje wartości domyślne podczas definiowania funkcji

c i d nie są zdefiniowane, nie istnieje, gdy tak się dzieje (istnieje tylko wtedy, gdy funkcja jest wykonywana)

„a, a = b” nie jest dozwolone w parametrze.

Aaditya Ura
źródło
0

Wymagane argumenty (te bez wartości domyślnych) muszą znajdować się na początku, aby kod klienta mógł dostarczyć tylko dwa. Gdyby opcjonalne argumenty znajdowały się na początku, byłoby mylące:

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

Co by to zrobiło w twoim pierwszym przykładzie? W ostatnim przypadku x to „kto jest kim”, y to 3, a a = „walet”.

cforbish
źródło