从列表理解和一般情况下有效地创建numpy数组

Nie*_*sGM 36 python performance numpy

在我目前的工作中,我使用Numpy和列表理解很多,为了最好的表现,我有以下问题:

如果我按如下方式创建Numpy数组,幕后实际发生了什么?:

a = numpy.array( [1,2,3,4] )
Run Code Online (Sandbox Code Playgroud)

我的猜测是python首先创建一个包含值的普通列表,然后使用列表大小来分配一个numpy数组,然后将值复制到这个新数组中.这是正确的,还是解释器聪明到足以意识到列表只是中介而是直接复制值?

同样,如果我希望使用numpy.fromiter()从列表理解中创建一个numpy数组:

a = numpy.fromiter( [ x for x in xrange(0,4) ], int )
Run Code Online (Sandbox Code Playgroud)

这会导致在被送入fromiter()之前创建的值的中间列表吗?

最好的问候尼尔斯

Sna*_*fee 40

我相信你正在寻找的是generator expressionsnumpy.fromiter一起使用的答案.

numpy.fromiter((<some_func>(x) for x in <something>),<dtype>,<size of something>)
Run Code Online (Sandbox Code Playgroud)

生成器表达式是惰性的 - 它们在迭代它们时评估表达式.

使用列表推导制作列表,然后将其提供给numpy,而生成器表达式将一次生成一个.

Python评估内部的东西 - > out,就像大多数语言一样(如果不是全部的话),所以使用[<something> for <something_else> in <something_different>]make会生成列表,然后迭代它.

  • numpy需要知道生成器的大小来为它分配内存.`np.fromiter`如何处理这个?存储生成的值,从而违背不生成列表或元组的目的?或者运行两次发生器,一次用于计数,另一次用于填充阵列? (16认同)
  • 从文档中可以清楚地看出来.*指定计数以提高性能.它允许fromiter预先分配输出数组,而不是根据需要调整它.*它会在你达到容量时重新分配数组.与C++中的`std :: vector`类似的行为 (5认同)
  • @Jaime发电机必须只运行一次!(想想副作用等等.)我没有在`numpy`中读过`fromiter`的源代码,但肯定`numpy.fromiter(something,int)`比`numpy.fromiter(list)更有效(某事),int)`.`numpy`可以使用`malloc` /`realloc`来创建`sizeof(int)`的对象数组.在Cpython中,`list`是异构对象的可变集合,因此它有一种更复杂的数据结构和分配策略. (2认同)

wim*_*wim 8

您可以创建自己的列表并进行实验,以了解情况......

>>> class my_list(list):
...     def __init__(self, arg):
...         print 'spam'
...         super(my_list, self).__init__(arg)
...   def __len__(self):
...       print 'eggs'
...       return super(my_list, self).__len__()
... 
>>> x = my_list([0,1,2,3])
spam
>>> len(x)
eggs
4
>>> import numpy as np
>>> np.array(x)
eggs
eggs
eggs
eggs
array([0, 1, 2, 3])
>>> np.fromiter(x, int)
array([0, 1, 2, 3])
>>> np.array(my_list([0,1,2,3]))
spam
eggs
eggs
eggs
eggs
array([0, 1, 2, 3])
Run Code Online (Sandbox Code Playgroud)