Por que as listas python têm pop () mas não push ()


265

Alguém sabe por que a list.appendfunção do Python não é chamada, list.pushjá que já existe um list.popque remove e retorna o último elemento (que é indexado em -1) e a list.appendsemântica é consistente com esse uso?


21
<nitpick> É um método, não uma função. </nitpick>
Tim Pietzcker 14/10/2009

49
Eu acho que essa é uma ótima pergunta, mas talvez deva ser formulada: "Por que as listas python têm pop (), mas não push ()".
Uri

6
poppode exibir itens de qualquer lugar da lista. appendnão pode "empurrar" algo para o meio de uma lista.
endolith 28/08

@TimPietzcker <nitpick ^ 2> O método também é uma função, o método (função membro) é um subconjunto da função :)
jave.web 05/03

Respostas:


246

Porque "anexar" existia muito antes de pensar em "pop". O Python 0.9.1 suportou list.append no início de 1991. Em comparação, aqui está parte de uma discussão sobre comp.lang.python sobre como adicionar pop em 1997. Guido escreveu:

Para implementar uma pilha, seria necessário adicionar uma primitiva list.pop () (e não, não sou contra essa em particular com base em qualquer princípio). list.push () pode ser adicionado para simetria com list.pop (), mas eu não sou um grande fã de vários nomes para a mesma operação - mais cedo ou mais tarde você lerá o código que usa o outro, então você precisa aprender os dois, que é mais carga cognitiva.

Você também pode ver que ele discute a idéia de se push / pop / put / pull deve estar no elemento [0] ou depois do elemento [-1], onde ele publica uma referência à lista de Icon:

Ainda acho que tudo isso é melhor deixar de fora da implementação do objeto de lista - se você precisar de uma pilha ou fila, com semântica específica, escreva uma pequena classe que use listas

Em outras palavras, para pilhas implementadas diretamente como listas Python, que já suportam append rápido () e del list [-1], faz sentido que list.pop () funcione por padrão no último elemento. Mesmo que outros idiomas façam isso de maneira diferente.

Está implícito aqui que a maioria das pessoas precisa anexar a uma lista, mas muito menos têm a oportunidade de tratar listas como pilhas, e é por isso que list.append apareceu muito antes.


16
@poige you're going to *read* code that uses the other one (...) which is more cognitive loadLembrar que "não há pressão" apenas introduz carga cognitiva quando você está escrevendo um código. Lembrar que "empurrar é um sinônimo exato para acrescentar" introduz a carga cognitiva sempre que você lê o que vê usado com menos frequência. Veja stackoverflow.com/questions/3455488/... para saber mais sobre por que as pessoas pensam a legibilidade muitas vezes supera writeability
stevenjackson121

2
Faz nenhuma desculpa / sentido
poige

15

Porque acrescenta; não empurra. "Anexar" adiciona ao final de uma lista, "pressionar" adiciona à frente.

Pense em uma fila versus uma pilha.

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

Editar: Para reformular minha segunda frase com mais precisão, "Anexar" muito claramente implica adicionar algo ao final de uma lista, independentemente da implementação subjacente. Onde um novo elemento é adicionado quando é "empurrado" é menos claro. Empurrar para uma pilha é colocar algo no "topo", mas o local onde ela realmente vai na estrutura de dados subjacente depende completamente da implementação. Por outro lado, empurrar para uma fila implica adicioná-la ao final.


4
O tutorial parece sugerir que simplesmente empurra e aparece do final: "Os métodos de lista facilitam o uso de uma lista como uma pilha, onde o último elemento adicionado é o primeiro elemento recuperado (" último a entrar, primeiro a sair "). Para adicionar um item ao topo da pilha, use append (). Para recuperar um item do topo da pilha, use pop () sem um índice explícito."
Uri

110
"empurrar" de forma alguma significa adicionar à frente. cada implementação de uma pilha que já foi escrito por um sane pessoa "empurra" para o topo (final) da pilha, não a parte inferior (início) da pilha
Kip

4
correção: toda * implementação baseada em array . uma implementação de lista vinculada levaria à tona.
Kip

16
javascript pushadiciona ao final.
Kobi

2
Não, considerando a list.popsemântica, list.appendenvia elementos para a lista, quando vistos como uma pilha.
fortran

10

Porque ele anexa um elemento a uma lista? Push é geralmente usado quando se refere a pilhas.


7
Uma lista pode ser uma pilha embora. :-)
Jason Baker

@JasonBaker Você pode implementar uma pilha usando uma lista, mas isso não significa lista == pilha. Você também pode implementar uma pilha usando uma fila, se realmente quiser. (Seria terrivelmente ineficiente, mas é possível!)
Mark E. Haase

A confusão realmente vem do fato de uma pilha não ter um "começo" ou "fim" como uma lista, mas sim um "topo" e um "fundo". Adicionar à pilha implica colocar um elemento na parte superior e "empurrar" para baixo. "Empurrar" na frente não faz sentido (pelo menos não linguisticamente). E apenas para tornar as coisas ainda mais confusas, o C ++ usa "push_front" e "push_back".
JesperE

9

Porque "acrescentar" intuitivamente significa "adicionar no final da lista". Se fosse chamado "push", não seria claro se estamos adicionando itens no final ou no início da lista.


12
Isso não faz sentido, pois há uma popoperação. Como pushe popnormalmente são operações de pilha e caminham juntas, deve-se esperar que elas operem no mesmo fim da lista.
jamesdlin

7

Não é uma resposta oficial de forma alguma (apenas um palpite baseado no uso da linguagem), mas o Python permite que você use listas como pilhas (por exemplo, seção 5.1.1 do tutorial ). No entanto, uma lista ainda é antes de tudo uma lista, portanto, as operações comuns a ambos usam termos de lista (ou seja, anexam) em vez de termos de pilha (ou seja, push). Como uma operação pop não é tão comum em listas (embora 'removeLast' possa ter sido usado), eles definiram um pop (), mas não um push ().


3

Ok, opinião pessoal aqui, mas Anexar e Anexar implicam posições precisas em um conjunto.

Push e Pop são realmente conceitos que podem ser aplicados a cada extremidade de um conjunto ... Contanto que você seja consistente ... Por alguma razão, para mim, Push () parece que deveria se aplicar à frente de um conjunto...


3
Desde que você o criou, se as matrizes têm uma função .append (), por que não existe uma função correspondente.prepend ()? Posso aprender a usar .insert (0, val) como prefixo, mas fico embaraçado com a falta de uma função .delete (pos, val) correspondente. ref: docs.python.org/2/library/array.html
MarkHu 5/12/12

3

Para sua informação, não é muito difícil fazer uma lista com um método 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]

Uma pilha é um tipo de dados um tanto abstrato. A idéia de "empurrar" e "estourar" é amplamente independente de como a pilha é realmente implementada. Por exemplo, você poderia implementar teoricamente uma pilha como esta (embora eu não saiba por que você faria):

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

... e eu não comecei a usar listas vinculadas para implementar uma pilha.


1

Push é um comportamento definido da pilha ; se você pressionasse A para empilhar (B, C, D), obteria (A, B, C, D).

Se você usou o python append, o conjunto de dados resultante seria semelhante a (B, C, D, A)

Edit: Uau, santo pedantismo.

Eu diria que, no meu exemplo, seria claro qual parte da lista é a parte superior e qual parte é a parte inferior. Supondo que a maioria de nós aqui leia da esquerda para a direita, o primeiro elemento de qualquer lista estará sempre à esquerda.


1
Isso não é verdade, o pop remove do final da lista, não da frente.
fortran

4
leia a página para a qual você vincula. push é definido como empurrar para o topo da pilha. qual final é o "topo" depende da implementação. em uma pilha baseada em matriz, o push seria empurrado para o final da matriz. em uma pilha baseada em lista vinculada, o push seria enviado para o início.
Kip

0

Provavelmente porque a versão original do Python ( C Python) foi escrita em C, não em C ++.

A idéia de que uma lista seja formada empurrando as coisas para trás de algo provavelmente não é tão conhecida quanto a ideia de anexá-las.


A segunda parte é uma boa resposta. Mas o que isso tem a ver com a implementação em C / C ++?
22630 Jason Baker

@ Jason: No STL do C ++, push_back () é como você anexa a uma lista. Eu estava tentando transmitir a meta-idéia de que a idéia de que as listas são formadas por push talvez seja mais provável que apareça se você estiver trabalhando em C ++. Faz algum sentido?
descontrair

Se você tiver um tipo de lista implementado como uma matriz contígua (um vetor em C ++, uma lista em Python, uma matriz em Perl), faz sentido que "push" coloque o novo elemento no final. Você deve notar que o perl 4 supõe "push" e "pop" como funções em matrizes exatamente como append / pop do Python e push_back / pop_back do C ++, e bem antes do STL ter sido formalmente proposto ao C ++. Portanto, isso não tem nada a ver com o STL do C ++, criando um novo entendimento das coisas.
22630 Andrew Dalke

Uma das coisas que sinto falta de aprender Python com base em Perl é a capacidade de usar as operações push (), pop (), shift () e unshift () internas para adicionar / remover elementos de / para as extremidades do mesmo array . Embora eu possa facilmente agrupar uma lista Python em uma classe "Stackish" ou "Queueish", não parece tão fácil (ou eficiente) fazer as duas coisas ao mesmo tempo.
Peter Peter

-2

Push e Pop fazem sentido em termos da metáfora de uma pilha de pratos ou bandejas em uma cafeteria ou bufê, especificamente aqueles no tipo de suporte que tem uma mola embaixo, de modo que o prato superior esteja (mais ou menos ... em teoria) no mesmo lugar, não importa quantas placas estejam embaixo.

Se você remover uma bandeja, o peso na mola é um pouco menor e a pilha "se soltará" um pouco; se você colocar a placa de volta, ela "empurra" a pilha para baixo. Portanto, se você pensa na lista como uma pilha e o último elemento está no topo, não deve ter muita confusão.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.