为什么python列表具有pop()但没有push()


265

有谁知道为什么list.append不调用Python的函数list.push,因为已经有一个list.pop删除并返回最后一个元素(索引为-1)并且list.append语义与该用法一致的原因?


21
<nitpick>这是一种方法,而不是函数。</ nitpick>
Tim Pietzcker,2009年

49
我认为这是一个很好的问题,尽管也许应该这样写:“为什么python列表有pop()但没有push()”。
Uri

6
pop可以从列表中的任何位置弹出项目。 append不能将某些东西“推入”列表的中间。
endlith 2014年

@TimPietzcker <nitpick ^ 2>实际上,方法也是函数,方法(成员函数)是函数的子集:)
jave.web

Answers:


246

因为“ append”早在想到“ pop”之前就已经存在。受Python 0.9.1支持的list.append于1991年初。通过比较,这是在comp.lang.python上讨论的有关在1997年添加pop 的一部分。Guido 写道:

为了实现一个堆栈,需要添加一个list.pop()原语(不,基于任何原则,我都不反对这种特定的堆栈)。可以添加list.push()使其与list.pop()对称,但是我不太喜欢针对同一操作使用多个名称-早晚要读取使用另一个名称的代码,所以您需要同时学习两者,这会增加认知负担。

您还可以看到他讨论了是否应该在元素[0]或元素[-1]之后或在元素[-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记住“没有推动力”只会在编写代码时引入认知负担。记住,“推式是append的确切同义词”会在每次阅读较少使用的单词时引入认知负荷。请参阅stackoverflow.com/questions/3455488/…了解更多有关为什么人们认为可读性通常胜过可写性的信息
stevenjackson121 '16

2
使得没有借口/感
poige

15

因为它附加;它不会推动。“添加”添加到列表的末尾,“推”添加到列表的前部。

想一想队列还是堆栈。

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

编辑:为了更准确地改写我的第二句话,“追加”非常清楚地意味着在列表的末尾添加一些内容,而不管其基础实现如何。当一个新元素被“推”到什么地方时,还不清楚。压入堆栈是将某些东西放在“顶部”,但是其在底层数据结构中的实际位置完全取决于实现。另一方面,推入队列意味着将其添加到末尾。


4
该教程似乎建议它只是从头开始弹出:“列表方法使将列表用作堆栈非常容易,其中最后添加的元素是检索到的第一个元素(“后进先出”)。 ”)。要向堆栈顶部添加项目,请使用append()。要从堆栈顶部检索项目,请使用不带显式索引的pop()。”
Uri 2009年

110
“推”绝不意味着增加正面。明智的人曾经将堆栈的每个实现“推”到堆栈的顶部(结束),而不是堆栈的底部(开始)
Kip

4
纠正:每个基于数组的实现。链表的实现将推到头。
Kip

16
javascript push添加到最后。
科比

2
不,考虑到list.pop语义list.append,当将其视为堆栈时,会将元素推入列表。
fortran

10

因为它将元素添加到列表?推栈通常在引用堆栈时使用。


7
列表可以是堆栈。:-)
杰森·贝克

@JasonBaker您可以使用列表实现堆栈,但这并不意味着list == stack。如果确实需要,也可以使用队列来实现堆栈。(这将是非常低效的,但是有可能!)
Mark E. Haase 2013年

混乱的真正原因是,堆栈没有像列表那样的“开始”或“结束”,而是“顶部”和“底部”。添加到堆栈中意味着将一个元素放在顶部,然后“向下推”。前面的“推”是没有意义的(至少在语言上没有意义)。为了使事情更加混乱,C ++使用了“ push_front”和“ push_back”。
JesperE

9

因为“添加”在直觉上意味着“在列表末尾添加”。如果它被称为“ push”,那么我们是否要在列表的末尾还是顶部添加内容尚不清楚。


12
因为有pop操作,所以这没有意义。由于pushpop通常是堆栈操作,并且一起进行,因此应该期望它们在列表的同一端进行操作。
jamesdlin

7

无论如何,这都不是正式的答案(只是基于使用该语言的猜测),但是Python允许您将列表用作堆栈(例如,本教程的5.1.1节)。但是,列表仍然是列表的第一位,因此,这两个共同的操作都使用列表项(即追加),而不是堆栈项(即推入)。由于弹出操作在列表中并不常见(尽管可以使用'removeLast'),所以他们定义了pop()而不是push()。


3

好的,这里有个人意见,但“追加”和“前置”表示集合中的精确位置。

Push和Pop确实是可以应用于集合两端的概念...只要您保持一致...出于某种原因,对我来说,Push()似乎应该应用于集合的前端组...


3
自从提出以来,如果数组具有.append()函数,那么为什么没有相应的.prepend()函数呢?我可以学习使用.insert(0,val)进行前缀,但是由于缺少相应的.delete(pos,val)函数而感到尴尬。参考: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

推送是定义的 堆栈行为;如果将A推入堆栈(B,C,D),您将得到(A,B,C,D)。

如果您使用python append,则结果数据集将看起来像(B,C,D,A)

编辑:哇,圣ped。

我认为从我的示例中可以清楚看出列表的哪一部分是顶部,哪一部分是底部。假设我们大多数人从左到右阅读,则任何列表的第一个元素始终将位于左侧。


1
事实并非如此,pop从列表的末尾而不是从列表的末尾删除。
fortran

4
阅读您链接到的页面。推入定义为推入堆栈的顶部。哪一端是“顶端”取决于实现方式。在基于数组的堆栈中,推入将推入数组的末尾。在基于链表的堆栈中,推入将推入开始。
基普(Kip)

0

可能是因为Python(C Python)的原始版本是用C而不是C ++编写的。

通过将事物推入事物的背面来形成列表的想法可能不如附加它们的想法众所周知。


第二部分是一个很好的答案。但是,用C / C ++实现又有什么关系呢?
杰森·贝克

@Jason:在C ++的STL中,push_back()是您追加到列表的方式。我试图传达一个元思想,即如果您使用的是C ++,则通过推送形成列表的想法可能更容易弹出。有道理吗?
放松

如果您将列表类型实现为连续数组(C ++中为矢量,Python中为列表,Perl中为数组),那么将“ push”放在新元素的末尾是有意义的。您会注意到,perl 4在数组上的功能完全像Python的append / pop和C ++的push_back / pop_back一样被认为是“ push”和“ pop”,并且早在STL正式提交给C ++之前就已经存在。因此,它与C ++的STL对事物的新理解无关。
2009年

我想从Perl的背景学习Python的一件事是能够使用内置的push(),pop(),shift()和unshift()操作在同一端的两端添加/删除元素的功能。数组。尽管我可以轻松地将Python列表包装在“ Stackish”类或“ Queueish”类中,但同时执行这两个任务看起来并不容易(或效率很高)。
彼得

-2

就自助餐厅或自助餐中一叠盘子或盘子的隐喻而言,“推”和“弹出”是有意义的,特别是在下方带有弹簧的顶托类型的托座(理论上或多或少...)在同一地方,无论下面有多少板。

如果卸下托盘,则弹簧上的重量会减小一点,并且纸叠会“弹起”一点,如果放回盘子,它会“压下”纸叠。因此,如果您将列表视为堆栈,而将最后一个元素视为顶部,那么您就不会感到太多困惑。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.