在Python中编程时,是否可以为将填充已知数量的项目的列表保留内存,以便在构建列表时不会多次重新分配列表?我查看了文档中的Python列表类型,但没有找到任何似乎这样做的东西。但是,这种类型的列表构建显示在我的代码的几个热点中,所以我想尽可能高效。
编辑:另外,用像Python这样的语言做这样的事情是否有意义?我是一个相当有经验的程序员,但是对Python很陌生并且仍然对它的做事方式有所了解。 Python是否在内部在单独的堆空间中分配所有对象,无法尝试最小化分配,或者是直接存储在列表中的原始内容,如整数,浮点数等?
答案 0 :(得分:34)
以下是四种变体:
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])*N
或numpy.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