在Python中保留内存列表?

当用Python进行编程时,是否可以为列表预留内存,列表中将填充已知数量的项目,以便在构build列表时不会多次重新分配列表? 我查看了Python列表types的文档,并没有发现任何似乎这样做的东西。 然而,这种types的列表build筑出现在我的代码的几个热点,所以我想尽可能高效。

编辑:另外,它甚至是有意义的,像Python这样的语言做这样的事情? 我是一个相当有经验的程序员,但是对于Python来说还是一个新手,并且仍然感觉到它的做事方式。 Python是否内部分配所有的对象在不同的​​堆空间中,破坏了试图最小化分配的目的,还是直接存储在列表中的int,float等原语?

这里有四个变种:

  • 增量列表创build
  • “预先分配”清单
  • array.array()
  • numpy.zeros()
python -mtimeit -s"N=10**6" "a = []; app = a.append;"\ "for i in xrange(N): app(i);" 10 loops, best of 3: 390 msec per loop python -mtimeit -s"N=10**6" "a = [None]*N; app = a.append;"\ "for i in xrange(N): a[i] = i" 10 loops, best of 3: 245 msec per loop python -mtimeit -s"from array import array; N=10**6" "a = array('i', [0]*N)"\ "for i in xrange(N):" " a[i] = i" 10 loops, best of 3: 541 msec per loop python -mtimeit -s"from numpy import zeros; N=10**6" "a = zeros(N,dtype='i')"\ "for i in xrange(N):" " a[i] = i" 10 loops, best of 3: 353 msec per loop 

它表明[None]*N是最快的, array.array在这种情况下是最慢的。

你可以像这样创build已知长度的列表:

 >>> [None] * known_number 

看看这个:

 In [7]: %timeit array.array('f', [0.0]*4000*1000) 1 loops, best of 3: 306 ms per loop In [8]: %timeit array.array('f', [0.0])*4000*1000 100 loops, best of 3: 5.96 ms per loop In [11]: %timeit np.zeros(4000*1000, dtype='f') 100 loops, best of 3: 6.04 ms per loop In [9]: %timeit [0.0]*4000*1000 10 loops, best of 3: 32.4 ms per loop 

所以不要使用array.array('f', [0.0]*N) ,使用array.array('f', [0.0])*Nnumpy.zeros

在大多数日常的代码中,你不需要这样的优化。

但是,当列表效率成为问题时,你应该做的第一件事是从array模块中replace通用列表和input一个更有效的array模块 。

以下是如何创build400万个浮点数的列表:

 import array lst = array.array('f', [0.0]*4000*1000) 

如果你想在Python中有效地操纵数字,那么看看NumPy( http://numpy.scipy.org/ )。 让你的东西非常快,而仍然使用Python。

为了做你在NumPy的要求,你会做类似的事情

 import numpy as np myarray = np.zeros(4000) 

这会给你一个初始化为零的浮点数的数组。 然后你可以做很酷的事情,比如用单一因子或者其他数组和其他的东西(比如在Matlab中,如果你曾经使用过这种types的东西)乘以整个数组,那么速度非常快(大部分的实际工作正在高度优化的NumPy库的C部分)。

如果它不是数组的数组,那么你可能不会find一种方法来在Python中做你想要的。 对象的Python列表是指向内部的对象列表(我认为无论如何,我不是Python内部专家),所以在创build它们时,它仍然会分配每个成员。

在Python中,所有对象都分配在堆上。
但是Python使用了一个特殊的内存分配器,所以每当你需要一个新的对象的时候malloc都不会被调用。
对于被caching的小整数(等等)也有一些优化。 然而,哪些types以及如何依赖于实现。

只需在开头创build列表就可以了:

 a = range(10) 

然后你可以赋值写作

 a[7] = an object