Pourquoi les listes python ont pop () mais pas push ()

265

Est-ce que quelqu'un sait pourquoi la list.appendfonction de Python n'est pas appelée list.pushétant donné qu'il y a déjà un list.popqui supprime et renvoie le dernier élément (celui indexé à -1) et la list.appendsémantique est cohérente avec cette utilisation?

Eddie Welker
la source
21
<nitpick> C'est une méthode, pas une fonction. </nitpick>
Tim Pietzcker
49
Je pense que c'est une excellente question, même si elle devrait peut-être être formulée: "Pourquoi les listes python ont-elles pop () mais pas push ()".
Uri
6
poppeut sortir des éléments de n'importe où dans une liste. appendne peut pas "pousser" quelque chose au milieu d'une liste.
endolith
@TimPietzcker <nitpick ^ 2> La méthode est, en effet, également une fonction, la méthode (fonction membre) est un sous-ensemble de la fonction :)
jave.web

Réponses:

246

Parce que "ajouter" existait bien avant que l'on pense à "pop". Python 0.9.1 supporte list.append au début de 1991. Par comparaison, voici une partie d'une discussion sur comp.lang.python sur l'ajout de pop en 1997. Guido a écrit:

Pour implémenter une pile, il faudrait ajouter une primitive list.pop () (et non, je ne suis pas contre celle-ci sur la base d'un principe). list.push () pourrait être ajouté pour la symétrie avec list.pop () mais je ne suis pas un grand fan de plusieurs noms pour la même opération - tôt ou tard vous allez lire du code qui utilise l'autre, donc vous devez apprendre les deux, ce qui représente davantage de charge cognitive.

Vous pouvez également voir qu'il discute de l'idée de savoir si push / pop / put / pull doit être à l'élément [0] ou après l'élément [-1] où il poste une référence à la liste des icônes:

Je pense toujours qu'il est préférable de laisser tout cela hors de l'implémentation de l'objet liste - si vous avez besoin d'une pile ou d'une file d'attente, avec une sémantique particulière, écrivez une petite classe qui utilise une liste

En d'autres termes, pour les piles implémentées directement en tant que listes Python, qui prennent déjà en charge fast append () et del list [-1], il est logique que list.pop () fonctionne par défaut sur le dernier élément. Même si d'autres langues le font différemment.

Implicitement, la plupart des gens ont besoin d'ajouter à une liste, mais beaucoup moins ont l'occasion de traiter les listes comme des piles, c'est pourquoi list.append est arrivé beaucoup plus tôt.

Andrew Dalke
la source
16
@poige you're going to *read* code that uses the other one (...) which is more cognitive loadSe souvenir "qu'il n'y a pas de poussée" n'introduit que la charge cognitive lorsque vous écrivez du code. Se souvenir de "push est un synonyme exact de append" introduit une charge cognitive chaque fois que vous lisez celle que vous voyez utilisée moins souvent. Voir stackoverflow.com/questions/3455488/… pour en savoir plus sur les raisons pour lesquelles les gens pensent que la lisibilité l'emporte souvent sur l'écriture
stevenjackson121
2
Ne
15

Parce qu'il ajoute; ça ne pousse pas. "Ajouter" ajoute à la fin d'une liste, "pousser" ajoute à l'avant.

Pensez à une file d'attente par rapport à une pile.

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

Edit: Pour reformuler ma deuxième phrase plus exactement, "Ajouter" implique très clairement d'ajouter quelque chose à la fin d'une liste, quelle que soit l'implémentation sous-jacente. L'endroit où un nouvel élément est ajouté lorsqu'il est "poussé" est moins clair. Pousser sur une pile, c'est mettre quelque chose au "dessus", mais où il va réellement dans la structure de données sous-jacente dépend complètement de l'implémentation. D'un autre côté, pousser dans une file d'attente implique de l'ajouter à la fin.

Matt Ball
la source
4
Le didacticiel semble suggérer qu'il pousse et saute simplement de la fin: "Les méthodes de liste rendent très facile l'utilisation d'une liste comme pile, où le dernier élément ajouté est le premier élément récupéré (" dernier entré, premier sorti " "). Pour ajouter un élément en haut de la pile, utilisez append (). Pour récupérer un élément du haut de la pile, utilisez pop () sans index explicite."
Uri
110
«pousser» ne signifie nullement ajouter à l'avant. chaque implémentation d'une pile qui a jamais été écrite par une personne sensée "pousse" en haut (fin) de la pile, pas en bas (début) de la pile
Kip
4
correction: chaque * implémentation basée sur un tableau . une mise en œuvre de liste chaînée pousserait à la tête.
Kip
16
javascript pushajoute à la fin.
Kobi
2
Non, compte tenu de la list.popsémantique, list.appendpousse les éléments dans la liste, lorsqu'ils sont vus comme une pile.
fortran
10

Parce qu'il ajoute un élément à une liste? Push est généralement utilisé pour faire référence aux piles.

JesperE
la source
7
Une liste peut cependant être une pile. :-)
Jason Baker
@JasonBaker Vous pouvez implémenter une pile à l'aide d'une liste, mais cela ne signifie pas la liste == pile. Vous pouvez également implémenter une pile à l'aide d'une file d'attente, si vous le souhaitez vraiment. (Ce serait horriblement inefficace, mais c'est possible!)
Mark E. Haase
La confusion vient vraiment du fait qu'une pile n'a pas de "début" ou de "fin" comme une liste, mais plutôt un "haut" et un "bas". Ajouter à la pile implique de placer un élément sur le dessus et de «pousser» vers le bas. "Pousser" à l'avant n'a aucun sens (du moins pas sur le plan linguistique). Et juste pour rendre les choses encore plus confuses, C ++ utilise "push_front" et "push_back".
JesperE
9

Parce que "ajouter" signifie intuitivement "ajouter à la fin de la liste". Si cela s'appelait "push", il serait difficile de savoir si nous ajoutons des éléments en queue ou en tête de liste.

Gyom
la source
12
Cela n'a pas de sens car il y a une popopération. Etant donné pushque ce popsont généralement des opérations de pile et vont de pair, il faut s'attendre à ce qu'elles fonctionnent à la même extrémité de la liste.
jamesdlin
7

Pas une réponse officielle par tous les moyens (juste une supposition basée sur l'utilisation de la langue), mais Python vous permet d'utiliser des listes comme piles (par exemple, la section 5.1.1 du tutoriel ). Cependant, une liste est avant tout une liste, donc les opérations qui sont communes aux deux utilisent des termes de liste (ie, ajouter) plutôt que des termes de pile (ie, push). Puisqu'une opération pop n'est pas si courante dans les listes (bien que 'removeLast' ait pu être utilisé), ils ont défini un pop () mais pas un push ().

Uri
la source
3

Ok, opinion personnelle ici, mais ajouter et ajouter des positions implicites précises dans un ensemble.

Push et Pop sont vraiment des concepts qui peuvent être appliqués à l'une ou l'autre extrémité d'un ensemble ... Aussi longtemps que vous êtes cohérent ... Pour une raison quelconque, Push () semble qu'il devrait s'appliquer à l'avant d'un ensemble...

dicroce
la source
3
Depuis que vous l'avez soulevée, si les tableaux ont une fonction .append (), alors pourquoi n'y a-t-il pas de fonction correspondante .prepend ()? Je peux apprendre à utiliser .insert (0, val) pour ajouter un préfixe, mais je suis alors gêné par l'absence d'une fonction .delete (pos, val) correspondante. ref: docs.python.org/2/library/array.html
MarkHu
3

Pour info, ce n'est pas très difficile de faire une liste qui a une méthode push:

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

Une pile est un type de données quelque peu abstrait. L'idée de «pousser» et de «sauter» est largement indépendante de la façon dont la pile est réellement mise en œuvre. Par exemple, vous pourriez théoriquement implémenter une pile comme celle-ci (bien que je ne sache pas pourquoi vous le feriez):

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

... et je n'ai pas commencé à utiliser des listes chaînées pour implémenter une pile.

Jason Baker
la source
1

Push est un comportement de pile défini ; si vous poussiez A sur la pile (B, C, D) vous obtiendrez (A, B, C, D).

Si vous avez utilisé python append, l'ensemble de données résultant ressemblerait à (B, C, D, A)

Edit: Wow, sainte pédanterie.

Je suppose que mon exemple montre clairement quelle partie de la liste est en haut et quelle partie en bas. En supposant que la plupart d'entre nous lisons ici de gauche à droite, le premier élément de toute liste sera toujours à gauche.

Satanicpuppy
la source
1
Ce n'est pas vrai, pop disparaît de la fin de la liste, pas du devant.
fortran
4
lire la page vers laquelle vous créez un lien. push est défini comme poussant vers le haut de la pile. quelle extrémité est le "top" dépend de la mise en œuvre. dans une pile basée sur un tableau, push pousserait à la fin du tableau. dans une pile basée sur une liste liée, push pousserait au début.
Kip
0

Probablement parce que la version originale de Python ( C Python) a été écrite en C, pas en C ++.

L'idée qu'une liste est formée en poussant les choses au dos de quelque chose n'est probablement pas aussi connue que l'idée de les annexer.

se détendre
la source
La deuxième partie est une bonne réponse. Mais qu'est-ce que cela a à voir avec l'implémentation en C / C ++?
Jason Baker
@Jason: Dans la STL de C ++, push_back () est la façon dont vous ajoutez à une liste. J'essayais de transmettre la méta-idée que l'idée que les listes sont formées en poussant est peut-être plus susceptible d'apparaître si vous travaillez en C ++. Ne veut rien dire?
détendez-vous
Si vous avez un type de liste implémenté comme un tableau contigu (un vecteur en C ++, une liste en Python, un tableau en Perl) alors il est logique d'avoir "push" pour mettre le nouvel élément à la fin. Vous remarquerez que perl 4 supposait que "push" et "pop" fonctionnaient sur des tableaux exactement comme append / pop de Python et push_back / pop_back de C ++, et bien avant que STL ne soit officiellement proposé à C ++. Cela n'a donc rien à voir avec le STL de C ++ qui crée une nouvelle compréhension des choses.
Andrew Dalke
L'une des choses qui me manque d'apprendre Python à partir d'un arrière-plan Perl est la possibilité d'utiliser les opérations push (), pop (), shift () et unshift () intégrées pour ajouter / supprimer des éléments de / vers l'une ou l'autre extrémité du même tableau . Même si je peux facilement envelopper une liste Python dans une classe "Stackish" ou une classe "Queueish", il ne semble pas si facile (ou efficace) de faire les deux à la fois.
Peter
-2

Push and Pop a du sens en termes de métaphore d'une pile d'assiettes ou de plateaux dans une cafétéria ou un buffet, en particulier ceux du type de support qui a un ressort en dessous de sorte que l'assiette supérieure est (plus ou moins ... en théorie) au même endroit, peu importe le nombre de plaques en dessous.

Si vous retirez un plateau, le poids sur le ressort est un peu moins élevé et la pile "ressort" un peu, si vous remettez la plaque, elle "pousse" la pile vers le bas. Donc, si vous pensez que la liste est une pile et que le dernier élément est en haut, vous ne devriez pas avoir beaucoup de confusion.

bob
la source