Dlaczego listy python mają pop (), ale nie push ()


265

Czy ktoś wie, dlaczego list.appendfunkcja Pythona nie jest wywoływana, list.pushbiorąc pod uwagę, że istnieje już element, list.popktóry usuwa i zwraca ostatni element (indeksowany jako -1), a list.appendsemantyczny jest zgodny z tym zastosowaniem?


21
<nitpick> To metoda, a nie funkcja. </nitpick>
Tim Pietzcker

49
Myślę, że to świetne pytanie, choć może powinno być sformułowane: „Dlaczego listy python mają pop (), ale nie push ()”.
Uri

6
popmoże wyskakiwać z dowolnego miejsca na liście. appendnie można „wepchnąć” czegoś na środek listy.
endolith

@TimPietzcker <nitpick ^ 2> Metoda jest rzeczywiście funkcją, metoda (funkcja członka) jest podzbiorem funkcji :)
jave.web

Odpowiedzi:


246

Ponieważ „append” istniało na długo przed myśleniem o „pop”. Lista obsługiwana przez Python 0.9.1. Dołącza na początku 1991 roku. Dla porównania, oto część dyskusji na temat comp.lang.python na temat dodawania popu w 1997 roku. Guido napisał:

Aby zaimplementować stos, należałoby dodać operację podstawową list.pop () (i nie, nie jestem przeciwny temu konkretnemu na podstawie jakiejkolwiek zasady). List.push () można dodać dla symetrii z list.pop (), ale nie jestem wielkim fanem wielu nazw dla tej samej operacji - prędzej czy później będziesz czytał kod, który używa drugiej, więc musisz nauczyć się obu, co jest bardziej obciążeniem poznawczym.

Możesz także zobaczyć, jak omawia pomysł, czy push / pop / put / pull powinien znajdować się w elemencie [0] lub za elementem [-1], w którym zamieszcza odwołanie do listy ikon:

Nadal uważam, że najlepiej to wszystko pominąć w implementacji obiektu listy - jeśli potrzebujesz stosu lub kolejki ze szczególną semantyką, napisz małą klasę, która używa list

Innymi słowy, dla stosów zaimplementowanych bezpośrednio jako listy Python, które już obsługują szybkie append () i del list [-1], sensowne jest, aby list.pop () domyślnie działał na ostatnim elemencie. Nawet jeśli inne języki robią to inaczej.

Domniemane jest to, że większość ludzi musi dołączyć się do listy, ale o wiele mniej ma okazję traktować listy jako stosy, dlatego lista list.append pojawiła się znacznie wcześniej.


16
@poige you're going to *read* code that uses the other one (...) which is more cognitive loadPamiętaj, że „nie ma push” wprowadza ładunek poznawczy tylko podczas pisania kodu. Pamiętanie, że „push jest dokładnym synonimem append”, wprowadza ładunek poznawczy, ilekroć czytasz ten, którego używasz rzadziej. Zobacz stackoverflow.com/questions/3455488/…, aby dowiedzieć się więcej o tym, dlaczego ludzie myślą, że czytelność często przebija zdolność do zapisu
stevenjackson121

2
Nie ma żadnego usprawiedliwienia / sensu
poige

15

Ponieważ dołącza się; nie pcha. „Dołączanie” dodaje na końcu listy, „pchanie” dodaje na początku.

Pomyśl o kolejce kontra stosie.

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

Edycja: Aby dokładnie przeredagować moje drugie zdanie, „Dołączanie” bardzo wyraźnie oznacza dodanie czegoś na końcu listy, niezależnie od podstawowej implementacji. To, gdzie nowy element zostanie dodany, gdy zostanie „wypchnięty”, jest mniej jasne. Wciśnięcie na stos oznacza umieszczenie czegoś na „górze”, ale to, gdzie faktycznie idzie w podstawowej strukturze danych, zależy całkowicie od implementacji. Z drugiej strony, wypychanie do kolejki oznacza dodawanie jej do końca.


4
Samouczek wydaje się sugerować, że po prostu popycha i wyskakuje od końca: „Metody list bardzo ułatwiają używanie listy jako stosu, w którym ostatni dodany element jest pierwszym pobieranym elementem („ ostatni na wejściu, pierwszy na wyjściu ” ”). Aby dodać element na górę stosu, użyj append (). Aby pobrać element ze szczytu stosu, użyj pop () bez wyraźnego indeksu.”
Uri

110
„pchanie” w żaden sposób nie oznacza dodawania z przodu. każda implementacja stosu, która kiedykolwiek została napisana przez zdrową osobę „wypycha” na górę (koniec) stosu, a nie na dół (początek) stosu
Kip

4
korekta: każda * implementacja tablicowa . wdrożenie listy połączonej zepchnęłoby do głowy.
Kip

16
javascript pushdodaje do końca.
Kobi

2
Nie, biorąc pod uwagę list.popsemantykę, list.appendwypycha elementy do listy, gdy jest postrzegane jako stos.
fortran

10

Ponieważ dołącza element do listy? Push odnosi się zwykle do stosów.


7
Listą może być jednak stos. :-)
Jason Baker

@JasonBaker Możesz zaimplementować stos za pomocą listy, ale to nie znaczy, że stos list ==. Możesz także zaimplementować stos za pomocą kolejki, jeśli naprawdę tego potrzebujesz. (Byłoby to okropnie nieefektywne, ale jest możliwe!)
Mark E. Haase

Zamieszanie naprawdę wynika z faktu, że stos nie ma „początku” ani „końca” jak lista, ale raczej „górę” i „dół”. Dodanie do stosu oznacza umieszczenie elementu na górze i „pchanie” w dół. „Pchanie” z przodu nie ma sensu (przynajmniej nie pod względem językowym). Aby jeszcze bardziej skomplikować sytuację, C ++ używa „push_front” i „push_back”.
JesperE

9

Ponieważ „dołącz” intuicyjnie oznacza „dodaj na końcu listy”. Gdyby nazywało się to „push”, nie byłoby jasne, czy dodajemy rzeczy na końcu czy na początku listy.


12
To nie ma sensu, ponieważ istnieje popoperacja. Ponieważ pushi popsą zwykle operacjami stosowymi i idą w parze, należy oczekiwać, że działają one na tym samym końcu listy.
jamesdlin,

7

Nie jest to oficjalna odpowiedź w żaden sposób (tylko zgadywanie oparte na użyciu języka), ale Python pozwala używać list jako stosów (np. Sekcja 5.1.1 samouczka ). Jednak lista wciąż jest przede wszystkim listą, więc operacje, które są wspólne dla obu, używają terminów listowych (tj. Dołączaj), a nie stosów (tj. Push). Ponieważ operacja pop nie jest tak powszechna na listach (chociaż można było użyć „removeLast”), zdefiniowano pop (), ale nie push ().


3

Ok, osobista opinia tutaj, ale Append and Prepend implikują precyzyjne pozycje w zestawie.

Push i Pop to tak naprawdę koncepcje, które można zastosować na każdym końcu zestawu ... Tak długo, jak jesteś konsekwentny ... Z jakiegoś powodu Push () wydaje się, że powinien mieć zastosowanie do przedniej części zestaw...


3
Skoro już o tym wspomniałeś, jeśli tablice mają funkcję .append (), to dlaczego nie ma odpowiadającej im funkcji .prepend ()? Mogę nauczyć się używać .insert (0, val) do dodawania, ale wstydzę się braku odpowiedniej funkcji .delete (pos, val). ref: docs.python.org/2/library/array.html
MarkHu,

3

Do twojej wiadomości, nie jest strasznie trudne stworzenie listy, która ma metodę 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]

Stos jest nieco abstrakcyjnym typem danych. Idea „wypychania” i „poppingu” jest w dużej mierze niezależna od tego, w jaki sposób stos jest faktycznie wdrażany. Na przykład możesz teoretycznie zaimplementować taki stos (chociaż nie wiem dlaczego):

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

... i nie wdałem się w używanie połączonych list do implementowania stosu.


1

Push jest zdefiniowanym zachowaniem stosu ; jeśli wepchniesz A na stos (B, C, D), dostaniesz (A, B, C, D).

Jeśli użyjesz Append Pythona, wynikowy zestaw danych będzie wyglądał następująco (B, C, D, A)

Edycja: Wow, święta pedanteria.

Zakładam, że z mojego przykładu jasno wynika, która część listy jest na górze, a która na dole. Zakładając, że większość z nas tutaj czyta od lewej do prawej, pierwszy element każdej listy zawsze będzie po lewej stronie.


1
To nie prawda, pop usuwa z końca listy, a nie z przodu.
fortran

4
przeczytaj stronę, do której linkujesz. push jest definiowane jako pchanie na wierzch stosu. który koniec jest „górą”, zależy od implementacji. w stosie opartym na tablicy, push wypychałby na koniec tablicy. w stosie opartym na listach połączonych push wypychałby na początek.
Kip

0

Prawdopodobnie dlatego, że oryginalna wersja Pythona ( C Python) została napisana w C, a nie w C ++.

Pomysł, że lista jest tworzona przez wypychanie rzeczy na tył czegoś, prawdopodobnie nie jest tak dobrze znany, jak myśl o ich dodaniu.


Druga część to dobra odpowiedź. Ale co to ma wspólnego z implementacją w C / C ++?
Jason Baker

@Jason: W STL C ++ push_back () to sposób dołączania do listy. Próbowałem przekazać meta-pomysł, że pomysł, że listy są tworzone przez wypychanie, jest bardziej prawdopodobne, że pojawi się, jeśli pracujesz w C ++. Mieć sens?
zrelaksuj się

Jeśli masz typ listy zaimplementowany jako ciągła tablica (wektor w C ++, lista w Pythonie, tablica w Perlu), wówczas sensowne jest, aby „push” umieścił nowy element na końcu. Zauważysz, że perl 4 powinien „wypychać” i „pop” jako funkcje na tablicach dokładnie tak, jak Python append / pop i C ++ push_back / pop_back, i na długo przed tym, zanim STL został formalnie zaproponowany do C ++. Nie ma to więc nic wspólnego z tym, że STL C ++ tworzy nowe rozumienie rzeczy.
Andrew Dalke

Jedną z rzeczy, za którymi tęsknię za nauką języka Python na tle Perla, jest możliwość korzystania z wbudowanych operacji push (), pop (), shift () i unshift () w celu dodawania / usuwania elementów do / z dowolnego końca tego samego tablica . Mimo że mogę z łatwością zawinąć listę Pythona w klasę „Stackish” lub „Queueish”, nie wydaje się to tak łatwe (ani wydajne), aby wykonywać oba te zadania jednocześnie.
Peter

-2

Push i Pop mają sens pod względem metafory stosu talerzy lub tacek w stołówce lub bufecie, szczególnie tych w rodzaju uchwytu, który ma sprężynę pod spodem, więc górna płyta jest (mniej więcej ... teoretycznie) w tym samym miejscu, bez względu na to, ile talerzy jest pod nim.

Jeśli wyjmiesz tacę, ciężar sprężyny będzie nieco mniejszy, a stos nieco „wyskoczy”, a jeśli odłożysz płytkę, „popchnie” stos w dół. Więc jeśli myślisz o liście jako o stosie, a ostatni element o tym, że jest na górze, nie powinieneś mieć większego zamieszania.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.