numpy数组和python列表是否被优化为动态增长?

时间:2016-12-09 14:34:03

标签: python arrays numpy optimization

我已经做了很多事情,要求我使用list .append()函数,以及numpy.append()函数用于numpy数组。我注意到,当数组的大小很大时,两者都会变得非常慢。

我需要一个动态增长的数组,大小约为100万个元素。我可以自己实现这个,就像std::vector是用C ++编写的那样,通过添加无法从外部访问的缓冲区长度(保留长度)。但我必须重新发明轮子吗?我想它应该在某个地方实现。所以我的问题是:Python中是否存在这样的事情?

我的意思是: Python中是否存在能够在大多数情况下以O(C)的时间复杂度动态增长的数组类型?

2 个答案:

答案 0 :(得分:1)

两者都使用底层数组。相反,您可以使用collections.deque来专门添加和删除两端的元素,其中O(1)复杂度

答案 1 :(得分:0)

numpy数组的内存在其文档中有详细描述,并在此处进行了大量讨论。列表内存布局也已经讨论过,但通常只与numpy形成鲜明对比。

numpy数组具有固定大小的数据缓冲区。 “增长”它需要创建一个新阵列,并将数据复制到它。 np.concatenate在编译代码中执行此操作。 np.append以及所有stack函数都使用concatenate

根据我的理解,列表包含一个连续的数据缓冲区,其中包含指向其他对象的指针。 Python在该缓冲区中维护了一些自由空间,因此list.append的添加相对快速而简单。但是当自由空间填满时,它必须创建一个新的缓冲区和复制指针。我可以看到大型列表可能会变得昂贵的地方。

因此,列表将存储每个元素的指针,以及内存中其他位置的元素本身(例如浮点数)。相比之下,浮点数组将浮点数本身存储为缓冲区中的连续字节。 (对象dtype数组更像列表)。

迭代创建数组的推荐方法是使用append构建列表,并在结尾创建一次数组。重复的np.appendnp.concatenate相对较贵。

提到了{p> deque。我不太了解它如何存储数据。文档说它可以在开始时添加元素,就像最后一样容易,但随机访问比列表慢。这意味着它将数据存储在某种链接列表中,因此查找nth元素需要在其之前遍历n-1链接。因此,在增长缓解和访问速度之间存在折衷。

将元素添加到列表的开头需要创建一个新的指针列表,并在开头添加新的指针。因此,从常规列表的开头添加和删除元素比在最后执行此操作要昂贵得多。

推荐软件不属于SO的核心目的。其他人可能会提出建议,但如果关闭则不要感到惊讶。

HDF5这样的文件格式是专为大型数据集设计的。它们通过“分块”等功能适应增长。并且有各种各样的数据库包。