不要在 numpy 中使用对象数组来处理这样的事情。
它们破坏了 numpy 数组的基本目的,虽然它们在少数情况下很有用,但它们几乎总是一个糟糕的选择。
是的,在 python 中访问 numpy 数组的单个元素或在 python 中遍历 numpy 数组比使用list
. (这就是为什么你永远不应该做类似y = [item * 2 for item in x]
whenx
是一个 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
还有其他方法可以做到这一点(例如,您可能希望避免在 each 中存储对特定numpy 数组的引用point
),但我希望这是一个有用的示例。
注意它们运行的速度差异。在我的机器上,numpy 版本相差 5 秒,而纯 python 版本相差 60 秒。