在Python中为列表保留内存?

时间:2009-02-11 14:41:15

标签: python performance arrays memory-management list

在Python中编程时,是否可以为将填充已知数量的项目的列表保留内存,以便在构建列表时不会多次重新分配列表?我查看了文档中的Python列表类型,但没有找到任何似乎这样做的东西。但是,这种类型的列表构建显示在我的代码的几个热点中,所以我想尽可能高效。

编辑:另外,用像Python这样的语言做这样的事情是否有意义?我是一个相当有经验的程序员,但是对Python很陌生并且仍然对它的做事方式有所了解。 Python是否在内部在单独的堆空间中分配所有对象,无法尝试最小化分配,或者是直接存储在列表中的原始内容,如整数,浮点数等?

7 个答案:

答案 0 :(得分:34)

以下是四种变体:

  • 创建增量列表
  • “预先分配”列表
  • 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是最慢的。

答案 1 :(得分:13)

您可以创建已知长度的列表,如下所示:

>>> [None] * known_number

答案 2 :(得分: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

答案 3 :(得分:5)

在大多数日常代码中,您不需要进行此类优化。

但是,当列表效率成为一个问题时,您应该做的第一件事就是用array module中的类型来替换通用列表,这样效率会更高。

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

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

答案 4 :(得分:4)

如果你想在Python中有效地操作数字,那么看看NumPy( http://numpy.scipy.org/)。它让你在开始使用Python时非常快速地完成任务。

要做你在NumPy中提出的问题,你会做类似

的事情
import numpy as np
myarray = np.zeros(4000)

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

如果它不是您之后的数字数组,那么您可能无法找到在Python中执行所需操作的方法。 Python的对象列表是内部对象的列表(我认为无论如何,我不是Python内部的专家)所以它仍然会在你创建它们时分配每个成员。

答案 5 :(得分:2)

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

答案 6 :(得分:0)

对于Python3:

import timeit
from numpy import zeros
from array import array

def func1():
    N=10**6
    a = []
    app = a.append
    for i in range(N):
        app(i)

def func2():
    N=10**6
    a = [None]*N
    app = a.append
    for i in range(N):
        a[i] = i

def func3():
    N=10**6
    a = array('i', [0]*N)
    for i in range(N):
        a[i] = i

def func4():
    N=10**6
    a = zeros(N,dtype='i')
    for i in range(N):
        a[i] = i

start_time = timeit.default_timer()
func1()
print(timeit.default_timer() - start_time)

start_time = timeit.default_timer()
func2()
print(timeit.default_timer() - start_time)

start_time = timeit.default_timer()
func3()
print(timeit.default_timer() - start_time)

start_time = timeit.default_timer()
func4()
print(timeit.default_timer() - start_time)

结果:

0.1655518
0.10920069999999998
0.1935983
0.15213890000000002
  1. append()
  2. [无] * N
  3. 使用模块数组
  4. 使用numpy模块