2009-02-11 92 views
37

当Python编程,是有可能保留内存,以便将与已知数量的项目填充一个列表,以便同时建立它的列表将不会被重新分配几次?我已经浏览了Python列表类型的文档,并没有发现任何似乎这样做的内容。然而,这种类型的列表建筑出现在我的代码的几个热点中,所以我想尽可能提高效率。为Python中的列表保留内存?

编辑:另外,它甚至是有意义的做这样的事情在像Python语言?我是一个相当有经验的程序员,但是对于Python来说是新手,并且仍然感受到它的做事方式。是否Python的内部分配在单独的堆空间都对象,击败试图最小化分配的目的,或像元整数,浮点数等直接存储在列表中?

+0

不要过早优化。 – ironfroggy 2010-01-31 15:19:52

+20

@ironfroggy:重点是,这**出现在热点**。在这些地方,名单建设造成了**重大的现实世界的瓶颈**,这是您应该优化的那种。 – dsimcha 2010-01-31 16:36:29

+0

可能重复[Python - 创建一个具有初始容量的列表](http://stackoverflow.com/questions/311775/python-create-a-list-with-initial-capacity) – 2015-05-06 04:28:25

回答

30

这里有四种形式:

  • 增量列表创建
  • “预分配” 列表
  • array.array()
  • numpy的。零()

 

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 

它表明​​是最快和array.array是在这种情况下最慢。

12

你可以这样创建已知长度的名单:

>>> [None] * known_number 
5

在最日常的代码,你不会需要这样的优化。

然而,当列表效率就成了一个问题,你应该做的第一件事就是更换输入一个从array module这是更为有效的泛型列表。

下面是400万浮点数cound列表创建:

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

你是什么意思“更多高效“? `array.array`可能需要更少的内存,但是Python列表在大多数情况下(意思是我尝试过的)情况更快。 – jfs 2009-02-11 15:24:48

+4

在这种情况下,它甚至会首先创建一个列表,然后从列表中创建一个数组。这不是有效的。 – 2009-02-11 15:52:19

2

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

4

如果你想在Python中有效地操纵数字,那么看看NumPy( http://numpy.scipy.org/)。它让你在非常快速的情况下完成任务,同时仍然可以使用Python。

做什么你在与NumPy问你会做这样的事情

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

这将使你的浮动初始化为零点数的数组。然后,你可以做很酷的事情,比如用单一因子或其他数组和其他数组(如果你曾经使用过这种类型,就像在Matlab中那样)乘以整个数组,这是非常快的(大部分实际工作发生在高度优化的NumPy库的C部分)。

如果不是数字的数组你那么之后你可能不会找到一种方法,你在Python想要什么。对象的Python列表是指向内部对象的列表(我认为无论如何,我不是Python内部专家),因此它在创建它们时仍将分配其每个成员。

8

在此请看:

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