不要在numpy中使用像这样的对象数组。
它们击败了numpy数组的基本目的,尽管它们在极少数情况下很有用,但它们几乎总是一个糟糕的选择。
是的,访问python中的numpy数组的单个元素或在python中遍历numpy数组比使用list
的等效操作要慢。 (这就是为什么你不应该做这样的事情y = [item * 2 for item in x]
时x
是numpy的阵列。)
numpy的对象数组将有小幅走低的内存开销比名单,但如果你存储许多个人Python对象,你首先会遇到其他内存问题。
Numpy首先是一个用于统一数字数据的内存高效的多维数组容器。如果你想在一个numpy数组中保存任意对象,你可能需要一个列表。
我的观点是,如果你想有效地使用numpy的,你可能需要重新思考你是如何构建的东西。
代替在一个numpy的阵列中存储每个对象实例,您的数值数据存储在numpy的阵列,并且如果需要单独的对象的每个行/列/不管,索引存储到在每一种情况下该数组。
这样就可以快速操作数值数组(即使用numpy代替列表解析)。
作为一个简单的例子就是我说一下,这里是不使用numpy的一个简单的例子:
from random import random
class PointSet(object):
def __init__(self, numpoints):
self.points = [Point(random(), random()) for _ in xrange(numpoints)]
def update(self):
for point in self.points:
point.x += random() - 0.5
point.y += random() - 0.5
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
points = PointSet(100000)
point = points.points[10]
for _ in xrange(1000):
points.update()
print 'Position of one point out of 100000:', point.x, point.y
而一个类似的例子使用numpy的数组:
import numpy as np
class PointSet(object):
def __init__(self, numpoints):
self.coords = np.random.random((numpoints, 2))
self.points = [Point(i, self.coords) for i in xrange(numpoints)]
def update(self):
"""Update along a random walk."""
# The "+=" is crucial here... We have to update "coords" in-place, in
# this case.
self.coords += np.random.random(self.coords.shape) - 0.5
class Point(object):
def __init__(self, i, coords):
self.i = i
self.coords = coords
@property
def x(self):
return self.coords[self.i,0]
@property
def y(self):
return self.coords[self.i,1]
points = PointSet(100000)
point = points.points[10]
for _ in xrange(1000):
points.update()
print 'Position of one point out of 100000:', point.x, point.y
还有其他的方法要做到这一点(例如,您可能希望避免在每个point
中存储对特定 numpy数组的引用),但我希望这是一个有用的示例。
请注意它们运行速度的差异。在我的机器上,numpy版本的差异是5秒,纯python版本的差异是60秒。