Semantik der Tupel entpacken in python
Warum python erlauben nur den benannten Argumenten zu Folgen, einen Tupel-Auspacken-Ausdruck in einer Funktion aufrufen?
>>> def f(a,b,c):
... print a, b, c
...
>>> f(*(1,2),3)
File "<stdin>", line 1
SyntaxError: only named arguments may follow *expression
Ist es einfach eine ästhetische Wahl, oder gibt es Fälle, wo erlaubt dies würde dazu führen, dass einige Unklarheiten?
- Sie können fügen Sie die Letzte argument des Tupels vor dem Auspacken.
- Eine interessante Frage. Ich scheine zu erinnern, die Regeln geändert, um python 2.5 - Sie verwendet zu haben, um die
*args
und**kwargs
am Ende, aber ich kann nicht finden die changelog-Eintrag.
Du musst angemeldet sein, um einen Kommentar abzugeben.
ich bin mir ziemlich sicher, dass der Grund, warum Menschen "natürlich" nicht mag, ist, dass es macht die Bedeutung der späteren Argumente mehrdeutig, je nach der Länge der interpolierten Reihe:
kann man nicht sagen, aus einem Blick auf die letzten beiden Anrufe zu
dangerbaby
denen man arbeitet wie erwartet und die man tötet kleine Kätzchen fluffykins.natürlich, etwas von dieser Unsicherheit ist auch vorhanden, wenn die Interpolation am Ende. aber die Verwirrung ist eingeschränkt auf die interpolierten Sequenz - es wirkt sich nicht auf andere Argumente, wie
bug
.[ich machte eine schnelle Suche, um zu sehen, ob ich finden konnte, nichts offizielles. es scheint, dass die * Präfix für varags war eingeführt in python 0.9.8. die Vorherige syntax wird diskutiert hier und die Regeln dafür, wie Sie gearbeitet wurden, ziemlich Komplex. da die Zugabe von zusätzlichen Argumente "musste" geschehen, am Ende, wenn es keine * Markierung wie es scheint,, dass Sie einfach übernommen. endlich gibt es eine hier erwähnen einer langen Diskussion über Argumente, die wurde nicht per E-Mail.]
Ich vermute, dass es für die Konsistenz mit der Stern-notation in Funktionsdefinitionen, die schließlich das Vorbild für die Stern-notation in Funktionsaufrufen.
In der folgenden definition der parameter
*c
wird slurp alle nachfolgenden nicht-keyword-Argumente, so offensichtlich, wennf
genannt wird, der einzige Weg, um einen Wert fürd
wird als Schlüsselwort-argument.(Wie "keyword-only-Parameter" werden nur unterstützt, in Python 3. In Python 2 gibt es ist keine Möglichkeit, Werte zuzuweisen, die nach einer Stern-argument, also das oben ist illegal.)
So, in einer Funktion definition das markierte argument Folgen muss, alle gewöhnlichen positions-Argumente. Was Sie beobachtet ist, dass die gleiche Regel wurde erweitert, um Funktionsaufrufe. So, die Sterne-syntax ist einheitlich für Funktionsdeklarationen und Funktionsaufrufe.
Andere Parallelität ist, dass Sie können nur eine (Einzel-)Stern-argument in einem Funktionsaufruf. Das folgende ist illegal, aber man könnte sich leicht vorstellen, dass es erlaubt ist.
f(*(1, 2), *(3, 4))
ist, dass die entsprechendenf(**{'a': 1}, **{'b': 2})
könnte führen zu Unklarheiten, wief(**{'a': 1}, **{'a': 2})
.Zuerst von allen, ist es einfach, um eine sehr ähnliche Schnittstelle selbst mit einem wrapper-Funktion:
Zweitens, die Verbesserung der interpreter zur Unterstützung Ihrer syntax nativ könnte hinzufügen overhead, um die sehr performance-kritische Aktivität-Funktion Anwendung. Auch wenn es erfordert nur ein paar zusätzliche Anweisungen in kompilierter code, aufgrund der hohen Nutzung dieser Routinen, das könnte bilden zu einer inakzeptablen performance-Einbußen im Austausch für ein feature, das nicht genannt für alle, die oft und leicht untergebracht in einer Anwender-Bibliothek.
Einige Beobachtungen:
f(c=3, *(1, 2))
in deinem Beispiel noch druckt1 2 3
). Dies macht Sinn, da (i) die meisten Argumente in Funktionsaufrufen werden die positions-und (ii) die Semantik einer Programmiersprache müssen eindeutig sein (d.h., eine Wahl, die vorgenommen werden muss so oder so auf die Reihenfolge, in der Prozess-positions-und Schlüsselwort-Argumente).f(*(1, 2), 3)
, sollte dasf(1, 2, 3)
oderf(3, 1, 2)
und warum hätte entweder die Wahl, die mehr Sinn machen als die anderen?def g(a, b, *c, d)
. Es gibt keine Möglichkeit, einen Wert fürd
andere als ein keyword-argument (positionale Argumente werden würde, 'packte' vonc
).ändern Sie die Reihenfolge:
(args,name=args,*args,**args)
Wenn Sie eine Python-3-Schlüsselwort-parameter nur, wie
dann könnten Sie erwarten, dass etwas wie
f(*(1, 2), 3)
zu setzena
zu(1 , 2)
undb
zu3
, aber natürlich, auch wenn die syntax, die Sie wollen, erlaubt, das wäre es nicht, weil keyword-only-Parameter werden müssen, die nur aus Keywords bestehen, wief(*(1, 2), b=3)
. Wenn Sie durften, ich denke es müsste uma
zu(1, 2, 3)
und lassenb
als Standard1
. So ist es vielleicht nicht die syntaktische Mehrdeutigkeit, so viel wie Mehrdeutigkeit in dem, was erwartet, was etwas ist Python stark versucht zu vermeiden.