Python 为什么从列表中弹出比追加要耗时?

Python 为什么从列表中弹出比追加要耗时?,python,algorithm,list,python-2.7,Python,Algorithm,List,Python 2.7,我在做一个简单的函数来重新排列一个没有太多元素的列表,比如100000或者可能一百万。 下面是函数的代码 def Rearrange(): global list1 list1.append(list1[0]) list1.pop(0) 基本上,这个just函数只是在列表的最后添加第一个元素并删除第一个元素。 当我包含函数的#2行时,对于100000大小的列表,运行函数所需的时间约为0.002秒,而如果我们将该行注释掉,只留下上面的语句,

我在做一个简单的函数来重新排列一个没有太多元素的列表,比如100000或者可能一百万。 下面是函数的代码

    def Rearrange():
        global list1
        list1.append(list1[0])
        list1.pop(0)
基本上,这个just函数只是在列表的最后添加第一个元素并删除第一个元素。

当我包含函数的#2行时,对于100000大小的列表,运行函数所需的时间约为0.002秒,而如果我们将该行注释掉,只留下上面的语句,则运行函数所需的时间约为5.2*10^-6秒。如何解释这一巨大差异?

Python列表是作为动态大小的数组实现的。因此,在数组中添加一个项目是便宜的,之后通常会有一些额外的位置。例如(只是一个示范性的例子,不保证确切的行为):

要弹出第一个元素,需要复制整个数组:

l.pop(0)
# 1 2 3 4 5 6 7 8 x x x x x x, 8 modifications!

这就不同了。

Python列表是作为动态大小的数组实现的。因此,在数组中添加一个项目是便宜的,之后通常会有一些额外的位置。例如(只是一个示范性的例子,不保证确切的行为):

要弹出第一个元素,需要复制整个数组:

l.pop(0)
# 1 2 3 4 5 6 7 8 x x x x x x, 8 modifications!
这就不同了。

来自:

也可以使用列表作为队列,其中第一个元素 添加的是检索到的第一个元素(“先进先出”);然而 列表在这方面并不有效。而从 列表的结尾很快,从列表的开头插入或弹出 列表很慢(因为所有其他元素都必须移位) 一个)

要实现队列,请使用设计为 快速从两端追加和弹出

因此,您看到计时的原因是,100000个元素的列表上的
pop(0)
需要复制99999个指针。

来自:

也可以使用列表作为队列,其中第一个元素 添加的是检索到的第一个元素(“先进先出”);然而 列表在这方面并不有效。而从 列表的结尾很快,从列表的开头插入或弹出 列表很慢(因为所有其他元素都必须移位) 一个)

要实现队列,请使用设计为 快速从两端追加和弹出


因此,您看到计时的原因是,100000个元素的列表上的
pop(0)
需要复制99999个指针。

追加只需在末尾添加新元素,但随着pop的出现,所有现有元素都必须向列表的开头移动一步

您正在寻找的是一个
deque
,它确保pop和append都是O(1)——请参阅

是的,Python列表确实做到了这一点,请参见该链接中的这一行:

虽然列表对象支持类似的操作,但它们针对快速的固定长度操作进行了优化,并为pop(0)和insert(0,v)操作带来了O(n)内存移动成本,这两种操作都会更改基础数据表示的大小和位置


append可以只在末尾添加新元素,但是使用pop时,所有现有元素都必须向列表的开头移动一步

您正在寻找的是一个
deque
,它确保pop和append都是O(1)——请参阅

是的,Python列表确实做到了这一点,请参见该链接中的这一行:

虽然列表对象支持类似的操作,但它们针对快速的固定长度操作进行了优化,并为pop(0)和insert(0,v)操作带来了O(n)内存移动成本,这两种操作都会更改基础数据表示的大小和位置


追加只能在末尾添加新元素,但对于pop,所有现有元素都必须向列表的开头移动。@RemcoGerlich python列表真的这样做了吗?是的,我将我的评论变成了答案。追加只能在末尾添加新元素,但对于pop,必须将所有现有元素移到列表的开头。@RemcoGerlich python列表真的做到了吗?是的,我把我的评论变成了答案。python列表中没有
add
方法。你的意思是
append
?从什么时候开始列表被实现为关联数组?因为Python已经存在了。请参阅通常意义的文档或@Danstahr:associative array(又名dictional)与“c array”(即连续内存块,这是列表在CPython中的实现方式)非常不同。@Tim:你完全正确,不知什么原因,我完全搞乱了我通常使用的术语,没有任何问题。当然,我指的是动态长度数组。python列表中没有
add
方法。你的意思是
append
?从什么时候开始列表被实现为关联数组?因为Python已经存在了。请参阅通常意义的文档或@Danstahr:associative array(又名dictional)与“c array”(即连续内存块,这是列表在CPython中的实现方式)非常不同。@Tim:你完全正确,不知什么原因,我完全搞乱了我通常使用的术语,没有任何问题。当然,我指的是动态长度数组。