¿Por qué las listas de Python tienen pop () pero no push ()

265

¿Alguien sabe por qué list.appendno se llama a la función de Python list.pushdado que ya hay un list.popque elimina y devuelve el último elemento (que está indexado en -1) y la list.appendsemántica es consistente con ese uso?

Eddie Welker
fuente
21
<nitpick> Es un método, no una función. </nitpick>
Tim Pietzcker
49
Creo que esta es una gran pregunta, aunque quizás debería estar redactada: "¿Por qué las listas de Python tienen pop () pero no push ()"?
Uri
66
poppuede sacar elementos de cualquier parte de una lista. appendno puede "empujar" algo en el medio de una lista.
endolito
@TimPietzcker <nitpick ^ 2> El método es, de hecho, también una función, el método (función miembro) es un subconjunto de funciones :)
jave.web

Respuestas:

246

Porque "agregar" existía mucho antes de que se pensara "pop". Python 0.9.1 admitió list.append a principios de 1991. En comparación, aquí hay parte de una discusión sobre comp.lang.python sobre agregar pop en 1997. Guido escribió:

Para implementar una pila, uno necesitaría agregar una primitiva list.pop () (y no, no estoy en contra de esta en particular sobre la base de ningún principio). list.push () podría agregarse por simetría con list.pop () pero no soy un gran admirador de los nombres múltiples para la misma operación; tarde o temprano leerás el código que usa el otro, así que necesitas aprender ambos, que es más carga cognitiva.

También puede ver que él discute la idea de si push / pop / put / pull debería estar en el elemento [0] o después del elemento [-1] donde publica una referencia a la lista de Icon:

Todavía creo que es mejor dejar todo esto fuera de la implementación del objeto de la lista: si necesita una pila o una cola, con una semántica particular, escriba una pequeña clase que use listas

En otras palabras, para las pilas implementadas directamente como listas de Python, que ya admiten el apéndice rápido () y del list [-1], tiene sentido que list.pop () funcione de manera predeterminada en el último elemento. Incluso si otros idiomas lo hacen de manera diferente.

Implícito aquí es que la mayoría de la gente necesita agregar una lista, pero muchos menos tienen la oportunidad de tratar las listas como pilas, por lo que list.append llegó mucho antes.

Andrew Dalke
fuente
16
@poige you're going to *read* code that uses the other one (...) which is more cognitive loadRecordar "no hay empuje" solo introduce una carga cognitiva cuando escribes código. Recordar que "empujar es un sinónimo exacto de agregar" introduce una carga cognitiva cada vez que lees el que ves que se usa con menos frecuencia. Consulte stackoverflow.com/questions/3455488/… para obtener más información acerca de por qué la gente piensa que la legibilidad a menudo triunfa sobre la capacidad de escritura
stevenjackson121
2
No tiene excusa / sentido
poige 01 de
15

Porque anexa; No empuja. "Agregar" se agrega al final de una lista, "presionar" se agrega al frente.

Piense en una cola frente a una pila.

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

Editar: Para reformular mi segunda oración más exactamente, "Agregar" implica claramente agregar algo al final de una lista, independientemente de la implementación subyacente. Donde un nuevo elemento se agrega cuando se "empuja" es menos claro. Empujar sobre una pila es poner algo en la "parte superior", pero donde realmente va en la estructura de datos subyacente depende completamente de la implementación. Por otro lado, empujar a una cola implica agregarlo al final.

Matt Ball
fuente
44
El tutorial parece sugerir que simplemente empuja y aparece desde el final: "Los métodos de lista hacen que sea muy fácil usar una lista como una pila, donde el último elemento agregado es el primer elemento recuperado (" último en entrar, primero en salir "). Para agregar un elemento a la parte superior de la pila, use append (). Para recuperar un elemento de la parte superior de la pila, use pop () sin un índice explícito."
Uri
110
"empujar" de ninguna manera significa agregar al frente. cada implementación de una pila que alguna vez haya sido escrita por una persona sensata "empuja" en la parte superior (extremo) de la pila, no en la parte inferior (inicio) de la pila
Kip
44
corrección: cada * implementación basada en matriz . una implementación de la lista enlazada se llevaría a la cabeza.
Kip
16
JavaScript se pushagrega al final.
Kobi
2
No, teniendo en cuenta la list.popsemántica, list.appendinserta elementos en la lista, cuando se ve como una pila.
fortran
10

¿Porque agrega un elemento a una lista? Push generalmente se usa cuando se refiere a las pilas.

JesperE
fuente
77
Sin embargo, una lista puede ser una pila. :-)
Jason Baker
@JasonBaker Puede implementar una pila usando una lista, pero eso no significa list == stack. También podría implementar una pila usando una cola, si realmente lo desea. (¡Sería terriblemente ineficiente, pero es posible!)
Mark E. Haase
La confusión realmente proviene del hecho de que una pila no tiene un "principio" o un "final" como una lista, sino más bien un "principio" y un "final". Agregar a la pila implica colocar un elemento en la parte superior y "empujar" hacia abajo. "Empujar" en el frente no tiene sentido (al menos no lingüísticamente). Y para hacer las cosas aún más confusas, C ++ usa "push_front" y "push_back".
JesperE
9

Porque "agregar" intuitivamente significa "agregar al final de la lista". Si se llamara "push", entonces no estaría claro si estamos agregando cosas en la cola o al principio de la lista.

Gyom
fuente
12
Esto no tiene sentido ya que hay una popoperación. Dado pushy popson típicamente operaciones de pila e ir juntos, es de esperar que operan en el mismo final de la lista.
jamesdlin
7

No es una respuesta oficial de ninguna manera (solo una suposición basada en el uso del lenguaje), pero Python le permite usar listas como pilas (por ejemplo, la sección 5.1.1 del tutorial ). Sin embargo, una lista sigue siendo, en primer lugar, una lista, por lo que las operaciones que son comunes a ambos usan términos de lista (es decir, agregar) en lugar de términos de pila (es decir, push). Como una operación pop no es tan común en las listas (aunque podría haberse usado 'removeLast'), definieron un pop () pero no un push ().

Uri
fuente
3

Ok, la opinión personal aquí, pero Añadir y Anteponer implica posiciones precisas en un conjunto.

Push y Pop son realmente conceptos que se pueden aplicar a cualquier extremo de un conjunto ... Siempre y cuando sea consistente ... Por alguna razón, para mí, Push () parece que debería aplicarse al frente de un conjunto...

dicroce
fuente
3
Desde que lo mencionó, si las matrices tienen una función .append (), ¿por qué no hay una función correspondiente.prepend ()? Puedo aprender a usar .insert (0, val) para anteponer, pero luego me avergüenzo por la falta de una función correspondiente .delete (pos, val). ref: docs.python.org/2/library/array.html
MarkHu
3

Para su información, no es terriblemente difícil hacer una lista que tenga un método de inserción:

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

Una pila es un tipo de datos algo abstracto. La idea de "empujar" y "estallar" es en gran medida independiente de cómo se implementa realmente la pila. Por ejemplo, teóricamente podrías implementar una pila como esta (aunque no sé por qué lo harías):

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

... y no me he acostumbrado a usar listas vinculadas para implementar una pila.

Jason Baker
fuente
1

Push es un comportamiento de pila definido ; si presionó A para apilar (B, C, D) obtendría (A, B, C, D).

Si usó python append, el conjunto de datos resultante se vería así (B, C, D, A)

Editar: Wow, santa pedantería.

Supongo que de mi ejemplo quedaría claro qué parte de la lista es la parte superior y qué parte es la parte inferior. Suponiendo que la mayoría de nosotros leemos de izquierda a derecha, el primer elemento de cualquier lista siempre estará a la izquierda.

Satanicpuppy
fuente
1
Eso no es cierto, pop elimina desde el final de la lista, no desde el frente.
fortran
44
lee la página a la que enlazas. empujar se define como empujar hacia la parte superior de la pila. qué final es el "top" depende de la implementación. en una pila basada en una matriz, push empujaría hacia el final de la matriz. en una pila basada en una lista vinculada, push empujaría al principio.
Kip
0

Probablemente porque la versión original de Python ( C Python) fue escrita en C, no en C ++.

La idea de que se forme una lista empujando cosas hacia atrás de algo probablemente no sea tan conocida como la idea de agregarlas.

relajarse
fuente
La segunda parte es una buena respuesta. Pero, ¿qué tiene eso que ver con la implementación en C / C ++?
Jason Baker
@Jason: en STL de C ++, push_back () es cómo se agrega a una lista. Estaba tratando de transmitir la meta idea de que la idea de que las listas se forman empujando es más probable que surja si estás trabajando en C ++. ¿Ningún sentido?
Descanse
Si tiene un tipo de lista implementado como una matriz contigua (un vector en C ++, una lista en Python, una matriz en Perl), entonces tiene sentido que "push" coloque el nuevo elemento al final. Notarás que perl 4 supuso "push" y "pop" como funciones en matrices exactamente como append / pop de Python y push_back / pop_back de C ++, y mucho antes de que STL se propusiera formalmente a C ++. Por lo tanto, no tiene nada que ver con el STL de C ++ que crea una nueva comprensión de las cosas.
Andrew Dalke
Una de las cosas que extraño aprender Python de un fondo Perl es la capacidad de usar las operaciones incorporadas push (), pop (), shift () y unshift () para agregar / eliminar elementos a / desde cualquier extremo del mismo matriz . Aunque puedo envolver fácilmente una lista de Python en una clase "Stackish" o una clase "Queueish", no parece tan fácil (o eficiente) hacer ambas cosas a la vez.
Peter
-2

Push and Pop tiene sentido en términos de la metáfora de una pila de platos o bandejas en una cafetería o buffet, específicamente en el tipo de soporte que tiene un resorte debajo, por lo que el plato superior es (más o menos ... en teoría) en el mismo lugar sin importar cuántas placas hay debajo.

Si retira una bandeja, el peso sobre el resorte es un poco menor y la pila "sube" un poco, si vuelve a colocar el plato, "empuja" la pila hacia abajo. Entonces, si piensa que la lista es una pila y el último elemento está en la parte superior, entonces no debería tener mucha confusión.

Beto
fuente