Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中为列表保留内存?_Python_Performance_Arrays_Memory Management_List - Fatal编程技术网

在Python中为列表保留内存?

在Python中为列表保留内存?,python,performance,arrays,memory-management,list,Python,Performance,Arrays,Memory Management,List,使用Python编程时,是否可以为将填充已知数量项的列表保留内存,以便在构建列表时不会多次重新分配列表?我在文档中查找了Python列表类型,但没有找到任何类似的方法。然而,这种类型的列表构建出现在我的代码的几个热点中,因此我希望使它尽可能高效 编辑:还有,在Python这样的语言中这样做有意义吗?我是一个相当有经验的程序员,但对Python还不熟悉,仍然对它的工作方式有感觉。Python是否在内部将所有对象分配到单独的堆空间中,从而破坏了尽量减少分配的目的,还是将int、float等原语直接存

使用Python编程时,是否可以为将填充已知数量项的列表保留内存,以便在构建列表时不会多次重新分配列表?我在文档中查找了Python列表类型,但没有找到任何类似的方法。然而,这种类型的列表构建出现在我的代码的几个热点中,因此我希望使它尽可能高效


编辑:还有,在Python这样的语言中这样做有意义吗?我是一个相当有经验的程序员,但对Python还不熟悉,仍然对它的工作方式有感觉。Python是否在内部将所有对象分配到单独的堆空间中,从而破坏了尽量减少分配的目的,还是将int、float等原语直接存储在列表中?

您可以这样创建已知长度的列表:

>>> [None] * known_number

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

然而,当列表效率成为一个问题时,您应该做的第一件事是将泛型列表替换为效率更高的类型化列表

下面是创建400万浮点数列表的方法:

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

在Python中,所有对象都在堆上分配。
但是Python使用了一个特殊的内存分配器,因此不会在每次需要新对象时调用
malloc


还有一些针对缓存的小整数(等)的优化;但是,哪些类型以及如何实现取决于实现。

如果您想在Python中高效地处理数字,那么就看看NumPy( ).它可以让您在使用Python的同时以极快的速度完成任务

要按照你在NumPy的要求做你会做的事情

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

如果不是后面的数字数组,那么您可能无法找到在Python中实现所需功能的方法。Python对象列表是指向内部对象的点的列表(无论如何,我认为是这样,我不是Python内部专家),因此在您创建它们时,它仍然会分配其每个成员。

以下是四种变体:

  • 增量列表创建
  • “预分配”清单
  • array.array()
  • numpy.zeros()

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

看看这个:

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)
,对于Python3,请使用
array.array('f',[0.0])*N
numpy.zeros

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
  • 附加()
  • [无]*N
  • 使用模块阵列
  • 使用模块numpy

  • 你说的“效率更高”是什么意思<代码>数组。数组可能需要更少的内存,但Python列表在大多数情况下(也就是我尝试过的那些情况)速度更快。在这种情况下,它甚至会先创建一个列表,然后从列表创建一个数组。这是没有效率的。@ironfroggy:关键是这在热点地区出现了。在这些地方,列表构建造成了一个重要的、现实世界中的瓶颈,您应该对其进行优化。我认为数组可能存在重复。这里使用数组的方式不太理想,请参见我的答案。@MikhailKorobov:好发现
    array('i',[0])*n
    along比
    array('i',[0]*n)
    快10倍,尽管如果添加初始化循环,它仍然比
    [0]*n
    variant慢。答案的要点是:先测量。代码示例来自当时的其他答案。这对numpy和array来说似乎有点不公平,因为您包括了导入时间,这可能会在很多调用中摊销@MikhailKorobov的结果似乎表明,numpy一旦被导入,速度要快得多。@MattKrause:the
    import
    不包括在内,注意
    -s
    @J.F.Sebastian使用a=[0]*n所有元素都有相同的引用,也就是说,如果我使用[0]=1,我将得到a=[1]*n。我想知道的是,当分配新内存时,结果是否相同?或者我做错了什么?如果你要设置数组元素而不是添加它们,你可能不需要零,只需要为每个元素保留一些空间。在这种情况下,方法是用
    np.empty
    代替
    np.zero
    。在你的测试中,我的计算机速度快了三倍。正如我在@Mikhail Korobov的回答中所说的,
    np.empty
    更可取,除非你真的需要数组从零开始,这样我的计算机速度就快了三倍。
    0.1655518
    0.10920069999999998
    0.1935983
    0.15213890000000002