Почему в списках Python есть pop (), а не push ()

265

Кто-нибудь знает, почему list.appendфункция Python не вызывается, list.pushучитывая, что уже есть a, list.popкоторый удаляет и возвращает последний элемент (индексированный в -1), и list.appendсемантика согласуется с этим использованием?

Эдди Велкер
источник
21
<nitpick> Это метод, а не функция. </ nitpick>
Тим Пицкер
49
Я думаю, что это отличный вопрос, хотя, возможно, его следует сформулировать так: «Почему в списках Python есть pop (), а не push ()».
Ури
6
popможет выскочить элементы из любого места в списке. appendне может «протолкнуть» что-то в середину списка.
эндолит
@TimPietzcker <nitpick ^ 2> Метод, действительно, также является функцией, метод (функция-член) является подмножеством функции :)
jave.web

Ответы:

246

Потому что «добавление» существовало задолго до того, как о «попсе» думали. Python 0.9.1 поддерживал list.append в начале 1991 года. Для сравнения, вот часть обсуждения на comp.lang.python о добавлении pop в 1997 году. Гвидо написал:

Чтобы реализовать стек, нужно добавить примитив list.pop () (и нет, я не против этого конкретного на основе какого-либо принципа). list.push () может быть добавлен для симметрии с list.pop (), но я не большой поклонник нескольких имен для одной и той же операции - рано или поздно вы будете читать код, который использует другую, поэтому вам нужно выучить и то, и другое, что является большей когнитивной нагрузкой.

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

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

Другими словами, для стеков, реализованных непосредственно как списки Python, которые уже поддерживают быстрые append () и 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
2
Не дает никаких оправданий / смысла
poige
15

Потому что это добавляет; это не толкает «Добавление» добавляет в конец списка, «добавление» добавляет вперед.

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

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

Изменить: Чтобы перефразировать мое второе предложение более точно, «Добавление» очень четко подразумевает добавление чего-либо в конец списка, независимо от базовой реализации. Где новый элемент добавляется, когда он «выдвинут», менее понятно. Выталкивание в стек ставит что-то на «вершину», но то, куда это фактически входит в базовую структуру данных, полностью зависит от реализации. С другой стороны, добавление в очередь подразумевает добавление ее в конец.

Мэтт Болл
источник
4
Похоже, что в учебном пособии предполагается, что оно просто выдвигается и всплывает с конца: «Методы списка позволяют очень легко использовать список в виде стека, где последний добавленный элемент - это первый извлеченный элемент (« последний пришел, первый вышел »). ”). Чтобы добавить элемент в начало стека, используйте append (). Чтобы извлечь элемент из верхней части стека, используйте pop () без явного индекса."
Uri
110
«толкать» ни в коем случае не значит добавлять вперед. каждая реализация стека, которая когда-либо была написана здравомыслящим человеком, «проталкивает» верх (конец) стека, а не низ (начало) стека
Kip
4
исправление: каждая * реализация на основе массива . реализация связанного списка подтолкнет к голове.
Кип
16
JavaScript pushдобавляет к концу.
Коби
2
Нет, учитывая list.popсемантику, list.appendпомещает элементы в список при просмотре в виде стека.
Фортран
10

Потому что он добавляет элемент в список? Push обычно используется при обращении к стекам.

JesperE
источник
7
Хотя список может быть стеком. :-)
Джейсон Бейкер
@JasonBaker Вы можете реализовать стек, используя список, но это не значит, что список == стек. Вы также можете реализовать стек, используя очередь, если вы действительно этого хотите. (Это было бы ужасно неэффективно, но возможно!)
Марк Э. Хааз
Путаница действительно связана с тем фактом, что стек не имеет «начало» или «конец», как список, а скорее «верх» и «низ». Добавление в стек подразумевает размещение элемента сверху и «толкание» вниз. «Толкать» впереди не имеет смысла (по крайней мере, не лингвистически). И просто, чтобы сделать вещи еще более запутанными, C ++ использует «push_front» и «push_back».
JesperE
9

Потому что «добавить» интуитивно означает «добавить в конец списка». Если бы это называлось «push», было бы неясно, добавляем ли мы что-то в конец или в начало списка.

Gyom
источник
12
Это не имеет смысла, так как есть popоперация. Так как pushи, popкак правило, являются стековыми операциями и идут вместе, следует ожидать, что они работают в одном конце списка.
jamesdlin
7

Ни в коем случае не официальный ответ (просто предположение, основанное на использовании языка), но Python позволяет использовать списки в качестве стеков (например, раздел 5.1.1 учебного пособия ). Тем не менее, список по-прежнему является прежде всего списком, поэтому операции, которые являются общими для обоих, используют термины списка (то есть, добавляют), а не термины стека (то есть, push). Поскольку операция pop не так часто встречается в списках (хотя можно было бы использовать removeLast), они определили pop (), но не push ().

Uri
источник
3

Хорошо, личное мнение здесь, но Append и Prepend подразумевают точные позиции в наборе.

Push и Pop - это действительно концепции, которые можно применять к любому концу набора ... До тех пор, пока вы последовательны ... По некоторым причинам, мне кажется, что Push () должен применяться к передней части набора. устанавливать...

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

К вашему сведению, не так уж сложно составить список с методом 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 append, результирующий набор данных будет выглядеть так (B, C, D, A)

Редактировать: Вау, священная педантичность.

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

Satanicpuppy
источник
1
Это не правда, поп удаляет из конца списка, а не спереди.
Фортран
4
прочитайте страницу, на которую вы ссылаетесь. push определяется как нажатие на вершину стека. какой конец является «верхом», зависит от реализации. в основанном на массиве стеке push будет выдвигаться в конец массива. в стеке на основе связанного списка push будет толкать в начало.
Кип
0

Возможно, потому что оригинальная версия Python ( C Python) была написана на C, а не на C ++.

Идея о том, что список формируется путем помещения чего-либо на задний план, вероятно, не так известна, как мысль о добавлении их в список.

размотать
источник
Вторая часть - хороший ответ. Но какое это имеет отношение к реализации в C / C ++?
Джейсон Бейкер
@Jason: в ST ++ C ++ push_back () - это то, как вы добавляете в список. Я пытался донести мета-идею о том, что идея о том, что списки формируются путем нажатия, возможно, будет более вероятной, если вы работаете в C ++. Иметь смысл?
расслабиться
Если у вас есть тип списка, реализованный в виде непрерывного массива (вектор в C ++, список в Python, массив в Perl), тогда имеет смысл «нажать», чтобы поместить новый элемент в конец. Обратите внимание, что Perl 4 предполагал «push» и «pop» в качестве функций для массивов, точно так же, как в Python append / pop и push_back / pop_back в C ++, и задолго до того, как STL был официально предложен для C ++. Так что это не имеет ничего общего с STL C ++, создающим новое понимание вещей.
Эндрю Далке
Одна из вещей, которые мне не нравятся при изучении Python на фоне Perl, - это возможность использовать встроенные операции push (), pop (), shift () и unshift () для добавления / удаления элементов с любого конца одного и того же конца. массив . Несмотря на то, что я легко могу обернуть список Python в класс «Stackish» или в класс «Queueish», это не так просто (или эффективно) сделать оба сразу.
Питер
-2

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

Если вы снимаете лоток, вес на пружине становится немного меньше, и стопка немного «поднимается» вверх, если вы ставите тарелку обратно, она «толкает» стопку вниз. Так что если вы думаете о списке как о стеке, а последний элемент - как о верхнем, то у вас не должно быть большой путаницы.

боб
источник