Warum können nicht standardmäßige Argumente nicht auf Standardargumente folgen?

137

Warum löst dieser Code einen SyntaxError aus?

  >>> 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

Während der folgende Code ohne sichtbare Fehler ausgeführt wird:

>>> def fun1(x, y, a="who is you", b="True"):
...     print a,b,x,y
... 
Dotslash
quelle
In Python ist die Struktur so, wenn Sie eine Funktion definieren def myfunction(position_arguments, *arguments, **keywords):"...."
abhishekgarg

Antworten:

172

Alle erforderlichen Parameter müssen vor Standardargumenten stehen. Einfach, weil sie obligatorisch sind, Standardargumente jedoch nicht. Syntaktisch wäre es für den Interpreter unmöglich zu entscheiden, welche Werte mit welchen Argumenten übereinstimmen, wenn gemischte Modi zulässig wären. A SyntaxErrorwird ausgelöst, wenn die Argumente nicht in der richtigen Reihenfolge angegeben werden:

Lassen Sie uns mit Ihrer Funktion einen Blick auf Schlüsselwortargumente werfen.

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

Angenommen, es ist erlaubt, die Funktion wie oben zu deklarieren. Dann können wir mit den obigen Deklarationen die folgenden (regulären) Positions- oder Schlüsselwortargumentaufrufe durchführen:

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

Wie Sie die Zuweisung von Variablen im Funktionsaufruf vorschlagen, wie Standardargumente zusammen mit Schlüsselwortargumenten verwendet werden.

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

Referenz O'Reilly - Core-Python
Wobei diese Funktion die Standardargumente verwendet, die für die obigen Funktionsaufrufe syntaktisch korrekt sind. Das Aufrufen von Schlüsselwortargumenten erweist sich als nützlich, um Positionsargumente außerhalb der Reihenfolge bereitstellen zu können. In Verbindung mit Standardargumenten können sie jedoch auch verwendet werden, um fehlende Argumente zu "überspringen".

Rahul Gautam
quelle
3
<q> Syntaktisch könnte der Interpreter nicht entscheiden, welche Werte mit welchen Argumenten übereinstimmen, wenn gemischte Modi zulässig wären. </ q> Ruby erlaubt nicht standardmäßige Argumente nach Standardargumenten. <q> Wie Sie die Zuweisung von Variablen im Funktionsaufruf vorschlagen </ q> Verwenden Sie einfach func1(x=1, y=2).
schwächer
Hallo @schwach, danke für den Kommentar, Python hat eine gute Möglichkeit, dies zu erreichen. Bitte suchen Sie nach * args und ** kwargs
Rahul Gautam
Hallo @Rahul Gautam, ich bin verwirrt. Ich dachte **kwargskann nicht def fun1(a="who is you", b="True", x, y)oder ähnliche Arbeit machen. Wenn Sie verwenden def f(**kwargs), müssen Sie Standardwerte im Körper behandeln?
schwächer
@schwach def fun1(a="who is you", b="True", x, y)das gleiche mit einem anderen Stil erreicht werden. Wenn def fun1 (** kwrgs) `, dann rufen Sie fun1({'a': 'who is you', 'b': True})keine Notwendigkeit auf, x und y zu übergeben.
Rahul Gautam
1
Warum schreiben Sie "Syntaktisch wäre es für den Interpreter unmöglich zu entscheiden, welche Werte mit welchen Argumenten übereinstimmen, wenn gemischte Modi zulässig wären."? Ich denke, dass der Algorithmus bei PEP 3102 genauso funktionieren könnte, selbst wenn def foo(x=None, y)dies zulässig wäre. Ich bin also immer noch neugierig, warum dies von Python nicht erlaubt wird. Gibt es einen wirklich fundamentalen Grund oder ist es nur "wir erlauben es nicht, weil wir es nicht erlauben".
Jeroen Demeyer
15
SyntaxError: non-default argument follows default argument

Wenn Sie dies zulassen, werden die Standardargumente unbrauchbar, da Sie ihre Standardwerte niemals verwenden können, da die nicht standardmäßigen Argumente nachher kommen .

In Python 3 können Sie jedoch Folgendes tun:

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

das macht xund ySchlüsselwort nur, damit Sie dies tun können:

fun1(x=2, y=2)

Dies funktioniert, weil keine Mehrdeutigkeit mehr besteht. Beachten Sie, fun1(2, 2)dass Sie dies immer noch nicht tun können (dies würde die Standardargumente festlegen).

Jamylak
quelle
Nur-Schlüsselwort-Argumente sind eine nette Funktion von Python 3. Schade, dass der Patch zum Zurückportieren auf Python 2.6 und 2.7 nur noch abgelaufen ist .
Nick Chammas
10

Lassen Sie mich hier zwei Punkte klarstellen:

  • Erstens sollte ein nicht standardmäßiges Argument nicht dem Standardargument folgen. Dies bedeutet, dass Sie in der Funktion nicht definieren können (a = b, c). Die Reihenfolge der Definition des Parameters in der Funktion ist:
    • Positionsparameter oder nicht standardmäßiger Parameter, dh (a, b, c)
    • Schlüsselwortparameter oder Standardparameter dh (a = "b", r = "j")
    • Nur-Schlüsselwort-Parameter dh (* args)
    • var-Schlüsselwortparameter dh (** kwargs)

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

(a, b) sind Positionsparameter

(c = keine) ist ein optionaler Parameter

(r = "w") ist der Schlüsselwortparameter

(d = []) ist der Listenparameter

(* ae) ist nur mit Schlüsselwörtern

(** ab) ist der var-Schlüsselwortparameter

  • Jetzt ist es zweitrangig, wenn ich so etwas versuche: def example(a, b, c=a,d=b):

Das Argument ist nicht definiert, wenn Standardwerte gespeichert werden. Python berechnet und speichert Standardwerte, wenn Sie die Funktion definieren

c und d sind nicht definiert, existieren nicht, wenn dies geschieht (es existiert nur, wenn die Funktion ausgeführt wird)

"a, a = b" ist im Parameter nicht erlaubt.

Aaditya Ura
quelle
0

Erforderliche Argumente (diejenigen ohne Standardeinstellungen) müssen am Anfang stehen, damit der Clientcode nur zwei liefern kann. Wenn die optionalen Argumente am Anfang wären, wäre dies verwirrend:

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

Was würde das in Ihrem ersten Beispiel tun? Im letzten ist x "wer ist wer", y ist 3 und a = "jack".

cforbish
quelle