Чому списки python мають pop (), але не push ()


265

Хтось знає, чому list.appendфункція Python не викликається, list.pushвраховуючи те, що вже є list.popтой, який видаляє та повертає останній елемент (індексований на -1), а list.appendсемантичний відповідає тому використанню?


21
<nitpick> Це метод, а не функція. </nitpick>
Тім Піцкер

49
Я думаю, що це велике запитання, хоча воно, можливо, має бути так: "Чому списки пітонів мають pop (), але не push ()".
Урі

6
popможе виводити елементи з будь-якого місця в списку. appendне може щось "натиснути" на середину списку.
ендоліт

@TimPietzcker <nitpick ^ 2> Метод, справді, також функція, метод (функція члена) є підмножиною функції :)
jave.web

Відповіді:


246

Тому що "додавання" існувало задовго до того, як про "поп" думали. Python 0.9.1 підтримує list.append на початку 1991 року. Для порівняння, ось частина дискусії на comp.lang.python про додавання pop у 1997 році. Guido писав:

Для реалізації стека потрібно додати примітив list.pop () (і ні, я не проти цього конкретного на основі будь-якого принципу). list.push () може бути доданий для симетрії з list.pop (), але я не великий фанат кількох імен для однієї операції - рано чи пізно ви будете читати код, який використовує інший, тож вам потрібно навчитися обом, що є більш пізнавальним навантаженням.

Ви також можете бачити, що він обговорює ідею, якщо push / pop / put / pull має бути в елементі [0] або після елемента [-1], де він публікує посилання на список Icon:

Я думаю, що все це краще залишити поза реалізацією об'єкта списку - якщо вам потрібен стек або черга з певною семантикою, напишіть невеликий клас, який використовує списки

Іншими словами, для стеків, реалізованих безпосередньо як списки Python, які вже підтримують швидке додавання (), і del list [-1], має сенс, що list.pop () працює за замовчуванням на останньому елементі. Навіть якщо інші мови роблять це по-іншому.

Тут очевидно, що більшості людей потрібно додавати до списку, але багато хто з них має привід трактувати списки як стеки, через що list.append з'явився набагато раніше.


16
@poige Пригадування you're going to *read* code that uses the other one (...) which is more cognitive load"немає поштовху" вводить когнітивне навантаження лише під час написання коду. Пам'ятаючи, що "push - точний синонім додавання", вводить когнітивне навантаження щоразу, коли ви читаєте ту, яку ви бачите, що використовується рідше. Дивіться stackoverflow.com/questions/3455488/… для отримання додаткової інформації про те, чому люди думають, що читаність часто козирує на письмі
stevenjackson121


15

Бо додається; це не штовхає. "Додавання" додає до кінця списку, "натискання" додає передню частину.

Придумайте чергу проти стека.

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

Редагувати: Щоб точніше переформулювати моє друге речення, "Звернення" дуже чітко означає, що щось додається до кінця списку, незалежно від основної реалізації. Де новий елемент додається, коли його "натискають", менш зрозуміло. Натискання на стек щось ставить на вершину, але те, де воно насправді перебуває в базовій структурі даних, повністю залежить від реалізації. З іншого боку, натискання на чергу передбачає додавання її до кінця.


4
Навчальний посібник, начебто, говорить про те, що він просто підштовхує та вискакує з кінця: "Методи списку дозволяють дуже просто використовувати список як стек, де останнім доданим елементом є перший отриманий елемент (" останній вхід, перший вихід ") ")" Щоб додати елемент у верхню частину стека, використовуйте додавання (). Щоб отримати елемент зверху стека, використовуйте pop () без явного індексу. "
Uri

110
"штовхати" жодним чином не означає додавати передню. кожна реалізація стека, яку коли-небудь писав розумний чоловік, "натискає" на верхню (кінець) стека, а не на нижню частину (старт) стека
Kip

4
виправлення: кожна * реалізація на основі масиву . реалізація пов'язаного списку підштовхне голову.
Кіп

16
javascript pushдодає до кінця.
Кобі

2
Ні, враховуючи list.popсемантику, list.appendвиштовхує елементи у список, якщо розглядати їх як стек.
фортран

10

Тому що він додає елемент до списку? Push зазвичай використовується при посиланні на стеки.


7
Список може бути стеком. :-)
Джейсон Бейкер

@JasonBaker Ви можете реалізувати стек за допомогою списку, але це не означає list == стек. Ви також можете реалізувати стек, використовуючи чергу, якщо дуже хотіли. (Це було б жахливо неефективно, але це можливо!)
Марк Е. Хааз

Плутанина насправді випливає з того, що стек не має "початку" або "кінця", як список, а скоріше "верх" і "низ". Додавання до стеку передбачає розміщення елемента вгорі і «штовхання» вниз. "Натискати" на фронт немає сенсу (принаймні, не лінгвістично). А щоб зробити речі ще більш заплутаними, C ++ використовує "push_front" та "push_back".
JesperE

9

Тому що "додавати" інтуїтивно означає "додати в кінці списку". Якби це називалося "push", тоді було б незрозуміло, додаємо ми речі в хвіст чи на початку списку.


12
Це не має сенсу, оскільки є popоперація. Так як pushі , popяк правило , стек операцій і йти разом, то слід очікувати , що вони працюють на тому ж самому кінці списку.
jamesdlin

7

Не офіційна відповідь будь-якими способами (лише здогадка на основі використання мови), але Python дозволяє використовувати списки як стеки (наприклад, розділ 5.1.1 підручника ). Однак список все-таки є передусім списком, тому операції, спільні для обох, використовують умови списку (тобто додавання), а не терміни стека (тобто, push). Оскільки поп-операція не так часто зустрічається у списках (хоча "RemoveLast" могла бути використана), вони визначили pop (), але не push ().


3

Гаразд, особиста думка тут, але додавання та подання передбачають точні позиції в наборі.

Push and Pop - це дійсно концепції, які можна застосувати до будь-якого кінця набору ... Тільки до тих пір, поки ви послідовні ... Мені чомусь Push () здається, що це має стосуватися передньої частини встановити ...


3
Оскільки ви його вивели, якщо масиви мають функцію .append (), то чому немає відповідної функції.prepend ()? Я можу навчитися використовувати .insert (0, val) для додавання, але мене потім бентежить відсутність відповідної функції .delete (pos, val). ref: docs.python.org/2/library/array.html
MarkHu

3

FYI, не важко скласти список, який має метод 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]

Стек - дещо абстрактний тип даних. Ідея «штовхати» та «вискакувати» значною мірою не залежить від того, як реально реалізується стек. Наприклад, ви теоретично можете реалізувати такий стек (хоча я не знаю, чому б це зробити):

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

... і я не ввійшов до використання пов'язаних списків для реалізації стека.


1

Push - це визначена поведінка стека ; якби ви натиснули A на стек (B, C, D), ви отримаєте (A, B, C, D).

Якщо ви використовуєте додаток python, отриманий набір даних буде виглядати так (B, C, D, A)

Редагувати: Вау, святий педантизм.

Я б припустив, що з мого прикладу було б зрозуміло, яка частина списку - це верхня, а яка - нижня. Якщо припустити, що більшість з нас тут читають зліва направо, перший елемент будь-якого списку завжди буде зліва.


1
Це неправда, поп видаляє з кінця списку, а не з фронту.
фортран

4
читайте сторінку, на яку ви посилаєтесь. натиск визначається як натискання на верхню частину стека. який кінець є «верхом», залежить від реалізації. у стеці на основі масиву натискання натисне на кінець масиву. у стеці на основі зв'язаного списку натискання наштовхнеться на початок.
Кіп

0

Можливо, тому, що оригінальна версія Python ( C Python) була написана на C, а не на C ++.

Ідея про те, що список складається шляхом натискання речей на задню частину чогось, напевно, не така відома, як думка про їх додавання.


Друга частина - хороша відповідь. Але що це стосується впровадження в C / C ++?
Джейсон Бейкер

@Jason: У STL C ++ push_back () - це спосіб додавання до списку. Я намагався донести мета-ідею про те, що ідея про те, що списки формуються натисканням, є, мабуть, більшою ймовірністю спливати, якщо ви працюєте в C ++. Маєш якийсь сенс?
розмотуватися

Якщо у вас є тип списку, реалізований у вигляді суміжного масиву (вектор у C ++, список у Python, масив у Perl), то має сенс "push" поставити новий елемент у кінець. Зауважте, що perl 4 передбачає "push" та "pop" як функції на масивах точно так само, як Python's append / pop та C ++'s push_back / pop_back, і задовго до того, як STL був офіційно запропонований на C ++. Тож це не має нічого спільного зі STL C ++, що створює нове розуміння речей.
Ендрю Далке

Одне з речей, які мені не вистачає при вивченні Python на фоні Perl, - це можливість використовувати вбудовані операції push (), pop (), shift () та unhift () для додавання / видалення елементів у / з будь-якого кінця того ж самого масив . Незважаючи на те, що я можу легко зафіксувати список Python в класі "Stackish" або "Queueish", зробити це одночасно не так просто (або ефективно).
Пітер

-2

Push and Pop мають сенс з точки зору метафори стопки тарілок або підносів у кафетерії чи фуршеті, зокрема тих, що мають тип тримача, який має пружину внизу, тому верхня тарілка є (більш-менш ... теоретично) там же, незалежно від того, скільки плит знаходиться під ним.

Якщо ви виймаєте лоток, вага на пружині трохи менший, а стопка трохи «спливає» вгору, якщо ви поставите тарілку назад, вона «штовхає» стопку вниз. Отже, якщо ви думаєте про список як про стек, а останній елемент як про верхній, то у вас не повинно виникати великої плутанини.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.