Warum haben Python-Listen pop (), aber nicht push ()

265

Weiß jemand, warum Pythons list.appendFunktion nicht aufgerufen list.pushwird, da es bereits eine gibt list.pop, die das letzte Element (das bei -1 indiziert ist) entfernt und zurückgibt und die list.appendSemantik mit dieser Verwendung übereinstimmt?

Eddie Welker
quelle
21
<nitpick> Es ist eine Methode, keine Funktion. </ nitpick>
Tim Pietzcker
49
Ich denke, dies ist eine großartige Frage, obwohl sie vielleicht formuliert werden sollte: "Warum haben Python-Listen pop (), aber nicht push ()".
Uri
6
popkann Elemente von überall in einer Liste herausspringen lassen. appendkann etwas nicht in die Mitte einer Liste "schieben".
Endolith
@TimPietzcker <nitpick ^ 2> Methode ist in der Tat auch eine Funktion, Methode (Mitgliedsfunktion) ist eine Teilmenge der Funktion :)
jave.web

Antworten:

246

Weil "Anhängen" lange vor dem Gedanken an "Pop" existierte. Python 0.9.1 unterstützte list.append Anfang 1991. Zum Vergleich: Hier ist ein Teil einer Diskussion über comp.lang.python über das Hinzufügen von Pop im Jahr 1997. Guido schrieb:

Um einen Stapel zu implementieren, müsste man ein Grundelement list.pop () hinzufügen (und nein, ich bin aufgrund eines Prinzips nicht gegen dieses spezielle Element). list.push () könnte aus Symmetriegründen mit list.pop () hinzugefügt werden, aber ich bin kein großer Fan von mehreren Namen für dieselbe Operation - früher oder später werden Sie Code lesen, der den anderen verwendet Sie müssen beides lernen, was eine höhere kognitive Belastung darstellt.

Sie können auch sehen, dass er die Idee diskutiert, ob Push / Pop / Put / Pull bei Element [0] oder nach Element [-1] sein sollte, wo er einen Verweis auf die Liste von Icon veröffentlicht:

Ich denke immer noch, dass all dies am besten in der Implementierung des Listenobjekts weggelassen wird. Wenn Sie einen Stapel oder eine Warteschlange mit einer bestimmten Semantik benötigen, schreiben Sie eine kleine Klasse, die Listen verwendet

Mit anderen Worten, für Stapel, die direkt als Python-Listen implementiert sind, die bereits fast append () und del list [-1] unterstützen, ist es sinnvoll, dass list.pop () standardmäßig für das letzte Element funktioniert. Auch wenn andere Sprachen es anders machen.

Dies impliziert, dass die meisten Leute an eine Liste anhängen müssen, aber viel weniger haben Gelegenheit, Listen als Stapel zu behandeln, weshalb list.append so viel früher einging.

Andrew Dalke
quelle
16
@poige Das you're going to *read* code that uses the other one (...) which is more cognitive loadErinnern an "es gibt keinen Push" führt nur zu einer kognitiven Belastung, wenn Sie Code schreiben. Wenn Sie sich daran erinnern, dass "Push ein genaues Synonym für Anhängen ist", wird die kognitive Belastung immer dann eingeführt, wenn Sie diejenige lesen, die weniger häufig verwendet wird. Unter stackoverflow.com/questions/3455488/… erfahren Sie mehr darüber, warum die Leute denken, dass Lesbarkeit oft die Schreibbarkeit übertrifft
stevenjackson121
2
Macht keine Entschuldigung / Sinn
poige
15

Weil es anhängt; es drückt nicht. "Anhängen" wird am Ende einer Liste hinzugefügt, "Drücken" wird an der Vorderseite hinzugefügt.

Stellen Sie sich eine Warteschlange gegen einen Stapel vor.

http://docs.python.org/tutorial/datastructures.html

Bearbeiten: Um meinen zweiten Satz genauer umzuformulieren, bedeutet "Anhängen" ganz klar, dass am Ende einer Liste etwas hinzugefügt wird , unabhängig von der zugrunde liegenden Implementierung. Wo ein neues Element hinzugefügt wird, wenn es "gepusht" wird, ist weniger klar. Wenn Sie auf einen Stapel schieben, wird etwas "oben" platziert, aber wo es tatsächlich in der zugrunde liegenden Datenstruktur hingeht, hängt vollständig von der Implementierung ab. Auf der anderen Seite bedeutet das Verschieben in eine Warteschlange, dass diese am Ende hinzugefügt wird.

Matt Ball
quelle
4
Das Tutorial scheint darauf hinzudeuten, dass es einfach vom Ende her verschoben und eingeblendet wird: "Die Listenmethoden machen es sehr einfach, eine Liste als Stapel zu verwenden, wobei das zuletzt hinzugefügte Element das erste abgerufene Element ist (" last-in, first-out " ”). Um ein Element oben im Stapel hinzuzufügen, verwenden Sie append (). Um ein Element oben im Stapel abzurufen, verwenden Sie pop () ohne expliziten Index."
Uri
110
"Drücken" bedeutet in keiner Weise, die Vorderseite zu erweitern. Jede Implementierung eines Stapels, die jemals von einer vernünftigen Person geschrieben wurde, "drückt" auf die Oberseite (Ende) des Stapels, nicht auf die Unterseite (Anfang) des Stapels
Kip
4
Korrektur: jede * Array-basierte Implementierung. Eine Implementierung mit verknüpften Listen würde den Kopf drücken.
Kip
16
Javascript pushfügt am Ende hinzu.
Kobi
2
Nein, unter Berücksichtigung der list.popSemantik werden list.appendElemente in die Liste verschoben, wenn sie als Stapel betrachtet werden.
Fortan
10

Weil es ein Element an eine Liste anfügt? Push wird normalerweise verwendet, wenn auf Stapel Bezug genommen wird.

JesperE
quelle
7
Eine Liste kann jedoch ein Stapel sein. :-)
Jason Baker
@JasonBaker Sie können einen Stack mithilfe einer Liste implementieren, dies bedeutet jedoch nicht list == stack. Sie können einen Stapel auch mithilfe einer Warteschlange implementieren, wenn Sie dies wirklich möchten. (Es wäre schrecklich ineffizient, aber es ist möglich!)
Mark E. Haase
Die Verwirrung kommt wirklich von der Tatsache, dass ein Stapel keinen "Anfang" oder "Ende" wie eine Liste hat, sondern einen "oberen" und einen "unteren". Das Hinzufügen zum Stapel bedeutet, dass ein Element oben platziert und nach unten "gedrückt" wird. "Pushing" vorne macht keinen Sinn (zumindest sprachlich nicht). Und um die Sache noch verwirrender zu machen, verwendet C ++ "push_front" und "push_back".
JesperE
9

Weil "Anhängen" intuitiv "am Ende der Liste hinzufügen" bedeutet. Wenn es "Push" genannt würde, wäre es unklar, ob wir Dinge am Ende oder am Anfang der Liste hinzufügen.

Gyom
quelle
12
Dies ist nicht sinnvoll, da eine popOperation vorliegt. Da pushund popin der Regel Stapeloperationen sind und zusammen gehören, sollte erwartet werden, dass sie am selben Ende der Liste ausgeführt werden.
Jamesdlin
7

Keine offizielle Antwort (nur eine Vermutung basierend auf der Verwendung der Sprache), aber Python ermöglicht es Ihnen, Listen als Stapel zu verwenden (z. B. Abschnitt 5.1.1 des Tutorials ). Eine Liste ist jedoch immer noch zuallererst eine Liste, daher verwenden die Operationen, die beiden gemeinsam sind, Listenbegriffe (dh Anhängen) anstelle von Stapelbegriffen (dh Push). Da eine Pop-Operation in Listen nicht so häufig vorkommt (obwohl 'removeLast' hätte verwendet werden können), haben sie ein pop (), aber kein push () definiert.

Uri
quelle
3

Ok, persönliche Meinung hier, aber Anhängen und Vorstellen implizieren präzise Positionen in einem Satz.

Push und Pop sind wirklich Konzepte, die auf jedes Ende eines Sets angewendet werden können ... Solange Sie konsistent sind ... Aus irgendeinem Grund scheint Push () aus irgendeinem Grund auf die Vorderseite von a anzuwenden einstellen...

Dicroce
quelle
3
Wenn Arrays eine .append () -Funktion haben, warum gibt es dann keine entsprechende.prepend () -Funktion? Ich kann lernen, .insert (0, val) zum Voranstellen zu verwenden, schäme mich dann aber für das Fehlen einer entsprechenden .delete-Funktion (pos, val). ref: docs.python.org/2/library/array.html
MarkHu
3

Zu Ihrer Information, es ist nicht besonders schwierig, eine Liste mit einer Push-Methode zu erstellen:

>>> class StackList(list):
...     def push(self, item):
...             self.append(item)
... 
>>> x = StackList([1,2,3])
>>> x
[1, 2, 3]
>>> x.push(4)
>>> x
[1, 2, 3, 4]

Ein Stapel ist ein etwas abstrakter Datentyp. Die Idee des "Drückens" und "Knallens" ist weitgehend unabhängig davon, wie der Stapel tatsächlich implementiert wird. Zum Beispiel könnten Sie theoretisch einen Stapel wie diesen implementieren (obwohl ich nicht weiß, warum Sie das tun würden):

l = [1,2,3]
l.insert(0, 1)
l.pop(0)

... und ich habe keine verknüpften Listen verwendet, um einen Stapel zu implementieren.

Jason Baker
quelle
1

Push ist ein definiertes Stapelverhalten . Wenn Sie A zum Stapeln (B, C, D) drücken, erhalten Sie (A, B, C, D).

Wenn Sie Python Append verwenden, sieht der resultierende Datensatz wie folgt aus (B, C, D, A).

Edit: Wow, heilige Pedanterie.

Ich würde annehmen, dass aus meinem Beispiel klar hervorgeht, welcher Teil der Liste oben und welcher Teil unten ist. Angenommen, die meisten von uns lesen hier von links nach rechts, dann befindet sich das erste Element einer Liste immer links.

Satanicpuppy
quelle
1
Das stimmt nicht, Pop wird am Ende der Liste entfernt, nicht von vorne.
Fortan
4
Lesen Sie die Seite, auf die Sie verlinken. Push ist definiert als Pushing auf die Oberseite des Stapels. Welches Ende das "Top" ist, hängt von der Implementierung ab. In einem Array-basierten Stapel würde Push auf das Ende des Arrays drücken. In einem auf verknüpften Listen basierenden Stapel würde Push an den Anfang verschoben.
Kip
0

Wahrscheinlich, weil die Originalversion von Python ( C Python) in C geschrieben wurde, nicht in C ++.

Die Idee, dass eine Liste gebildet wird, indem Dinge auf den Rücken von etwas geschoben werden, ist wahrscheinlich nicht so bekannt wie der Gedanke, sie anzuhängen.

entspannen
quelle
Der zweite Teil ist eine gute Antwort. Aber was hat das mit der Implementierung in C / C ++ zu tun?
Jason Baker
@Jason: In C ++ 's STL hängen Sie mit push_back () an eine Liste an. Ich habe versucht, die Meta-Idee zu vermitteln, dass die Idee, dass Listen durch Pushing gebildet werden, möglicherweise eher auftaucht, wenn Sie in C ++ arbeiten. Sinn machen?
Entspannen Sie
Wenn Sie einen Listentyp als zusammenhängendes Array implementiert haben (ein Vektor in C ++, eine Liste in Python, ein Array in Perl), ist es sinnvoll, das neue Element durch "Push" am Ende zu setzen. Sie werden bitte beachten, dass Perl 4 "Push" und "Pop" als Funktionen auf Arrays genau wie Pythons Append / Pop und C ++ 's Push_back / Pop_back angenommen hat, lange bevor STL offiziell für C ++ vorgeschlagen wurde. Es hat also nichts damit zu tun, dass die STL von C ++ ein neues Verständnis der Dinge schafft.
Andrew Dalke
Eines der Dinge, die ich vermisse, wenn ich Python aus einem Perl-Hintergrund lerne, ist die Möglichkeit, integrierte push () -, pop () -, shift () - und unshift () -Operationen zu verwenden, um Elemente zu / von beiden Enden derselben hinzuzufügen / zu entfernen Array . Obwohl ich eine Python-Liste leicht in eine "Stackish" -Klasse oder eine "Queueish" -Klasse einbinden kann, sieht es nicht so einfach (oder effizient) aus, beides gleichzeitig zu tun.
Peter
-2

Push and Pop ist in Bezug auf die Metapher eines Stapels von Tellern oder Tabletts in einer Cafeteria oder einem Buffet sinnvoll, insbesondere in Bezug auf die Art des Halters, unter dem sich eine Feder befindet, so dass sich der obere Teller befindet (mehr oder weniger ... theoretisch). an der gleichen Stelle, egal wie viele Teller darunter sind.

Wenn Sie ein Tablett entfernen, ist das Gewicht der Feder etwas geringer und der Stapel "springt" ein wenig nach oben. Wenn Sie die Platte zurücklegen, "drückt" sie den Stapel nach unten. Wenn Sie also die Liste als Stapel und das letzte Element als oben betrachten, sollten Sie nicht viel Verwirrung stiften.

Bob
quelle