Python numpy数组与列表

Python numpy数组与列表,python,arrays,list,numpy,Python,Arrays,List,Numpy,我需要对一大串数字进行一些计算 与典型阵列相比,array.array或numpy.array是否提供了显著的性能提升 我不需要对数组进行复杂的操作,我只需要能够访问和修改值 e、 g 因此,我将不会真正需要连接、切片等 另外,如果我尝试分配不适合C long的值,数组似乎会抛出一个错误: import numpy a = numpy.array([0]) a[0] += 1232234234234324353453453 print(a) 在控制台上,我得到: a[0] += 1232234

我需要对一大串数字进行一些计算

与典型阵列相比,array.array或numpy.array是否提供了显著的性能提升

我不需要对数组进行复杂的操作,我只需要能够访问和修改值

e、 g

因此,我将不会真正需要连接、切片等

另外,如果我尝试分配不适合C long的值,数组似乎会抛出一个错误:

import numpy
a = numpy.array([0])
a[0] += 1232234234234324353453453
print(a)
在控制台上,我得到:

a[0] += 1232234234234324353453453
OverflowError: Python int too large to convert to C long
数组是否有一种变体可以让我输入无界Python整数?
或者,这样做会不会从一开始就失去使用数组的意义?

您首先需要了解数组和列表之间的区别

数组是一个连续的内存块,由某些类型的元素(例如整数)组成

一旦创建数组,就不能更改其大小。
因此,数组中的每个整数元素都有固定的大小,例如4个字节

另一方面,列表仅仅是地址的“数组”(也有固定大小)

但是,每个元素都保存内存中其他元素的地址,这是您想要处理的实际整数。当然,这个整数的大小与数组的大小无关。因此,您总是可以创建一个新的(更大的)整数,并“替换”旧整数,而不影响数组的大小,数组只保存整数的地址

当然,列表的这种便利性是有代价的:对整数执行算术现在需要对数组进行内存访问,加上对整数本身的内存访问,加上分配更多内存所需的时间(如果需要),加上删除旧整数所需的时间(如果需要的话)。是的,它可能会慢一些,所以你必须小心处理数组中的每个整数

与典型阵列相比,array.array或numpy.array是否提供了显著的性能提升

它可以,取决于你在做什么

或者,这样做会不会从一开始就失去阵列的意义


差不多,是的。

您的第一个示例可能是加速。Python循环和对numpy数组中单个项的访问速度很慢。请改用矢量化操作:

import numpy as np
x = np.arange(1000000).cumsum()
可以将无界Python整数放入numpy数组:

a = np.array([0], dtype=object)
a[0] += 1232234234234324353453453
在这种情况下,算术运算比固定大小的C整数要慢

array.array或numpy.array是否比 典型阵列

我尝试用以下代码对此进行测试:

import timeit, math, array
from functools import partial
import numpy as np

# from the question
def calc1(x):
    for i in range(1,len(x)):
        x[i] = x[i-1] + 1

# a floating point operation
def calc2(x):
    for i in range(0,len(x)):
        x[i] = math.sin(i)

L = int(1e5)

# np
print('np 1: {:.5f} s'.format(timeit.timeit(partial(calc1, np.array([0] * L)), number=20)))
print('np 2: {:.5f} s'.format(timeit.timeit(partial(calc2, np.array([0] * L)), number=20)))

# np but with vectorized form
vfunc = np.vectorize(math.sin)
print('np 2 vectorized: {:.5f} s'.format(timeit.timeit(partial(vfunc, np.arange(0, L)), number=20)))

# with list
print('list 1: {:.5f} s'.format(timeit.timeit(partial(calc1, [0] * L), number=20)))
print('list 2: {:.5f} s'.format(timeit.timeit(partial(calc2, [0] * L), number=20)))

# with array
print('array 1: {:.5f} s'.format(timeit.timeit(partial(calc1, array.array("f", [0] * L)), number=20)))
print('array 2: {:.5f} s'.format(timeit.timeit(partial(calc2, array.array("f", [0] * L)), number=20)))
结果是列表在这里执行得最快(Python 3.3,NumPy 1.8):


这似乎是违反直觉的。对于这些简单的示例,使用
numpy
array
而不是
list
似乎没有任何优势。

使用
a=numpy.array(元素数,dtype=numpy.int64)
这将为您提供一个64位整数数组。它们可以存储-2^63和(2^63)-1之间的任何整数(大约在-10^19和10^19之间),这通常就足够了。

对于大多数用途,列表非常有用。例如,有时使用numpy数组可能更方便

a=[1,2,3,4,5,6,7,8,9,10]

b=[5,8,9]
考虑一个列表“a”,如果您想访问列表中的元素,请使用列表“b”中给出的离散索引 书写

这是行不通的

但当您将它们用作数组时,您只需编写

a[b]

以数组([6,9,10])的形式获取输出。

到OP:For your use case use list

考虑到稳健性和速度,我的使用规则如下:

列表:(最健壮,对于可变情况最快) 例如,当你的列表在物理模拟中不断变化时。当你从头开始“创建”数据时,这些数据在本质上可能是不可预测的

np.array:(线性代数和数据后处理的鲁棒性较差,速度最快)
例如,“后处理”通过传感器或模拟采集的数据集;执行可矢量化的操作。

如果不使用矢量化操作(如OP的第一个示例),最后一段同样适用于固定大小整数的numpy数组。这不是numpy阵列速度更快的原因。另请参见
a=[1,2,3,4,5,6,7,8,9,10]

b=[5,8,9]
a[b]
a[b]