Я согласен с тем, что параллельные массивы почти всегда являются плохой идеей, но не забывайте, что вы можете использовать представления в массивном массиве при настройке, хотя ... (Да, я знаю, это эффективно используя параллельные массивы, но я думаю, что это лучший вариант в этом случае ...)
Это замечательно, если вы знаете заранее количество «шариков», которые вы собираетесь создать, поскольку вы можете выделить массив для координат и сохранить представление в этом массиве для каждого объекта шарика.
Вы должны быть немного осторожны, чтобы выполнять операции на месте в массиве координат, но это делает обновление координат для множества "шаров" намного, намного, намного быстрее.
Например ...
import numpy as np
class Ball(object):
def __init__(self, coords):
self.coords = coords
def _set_coord(self, i, value):
self.coords[i] = value
x = property(lambda self: self.coords[0],
lambda self, value: self._set_coord(0, value))
y = property(lambda self: self.coords[1],
lambda self, value: self._set_coord(1, value))
def move(self, dx, dy):
self.x += dx
self.y += dy
def main():
n_balls = 10
n_dims = 2
coords = np.zeros((n_balls, n_dims))
balls = [Ball(coords[i,:]) for i in range(n_balls)]
# Just to illustrate that that the coords are updating
ball = balls[0]
# Random walk by updating coords array
print 'Moving all the balls randomly by updating coords'
for step in xrange(5):
# Add a random value to all coordinates
coords += 0.5 - np.random.random((n_balls, n_dims))
# Display the coords for a particular ball and the
# corresponding row of the coords array
print ' Value of ball.x, ball.y:', ball.x, ball.y
print ' Value of coords[0,:]:', coords[0,:]
# Move an individual ball object
print 'Moving a ball individually through Ball.move()'
ball.move(0.5, 0.5)
print ' Value of ball.x, ball.y:', ball.x, ball.y
print ' Value of coords[0,:]:', coords[0,:]
main()
Просто чтобы проиллюстрировать, это выводит что-то вроде:
Moving all the balls randomly by updating coords
Value of ball.x, ball.y: -0.125713650677 0.301692195466
Value of coords[0,:]: [-0.12571365 0.3016922 ]
Value of ball.x, ball.y: -0.304516863495 -0.0447543559805
Value of coords[0,:]: [-0.30451686 -0.04475436]
Value of ball.x, ball.y: -0.171589457954 0.334844443821
Value of coords[0,:]: [-0.17158946 0.33484444]
Value of ball.x, ball.y: -0.0452864552743 -0.0297552313656
Value of coords[0,:]: [-0.04528646 -0.02975523]
Value of ball.x, ball.y: -0.163829876915 0.0153203173857
Value of coords[0,:]: [-0.16382988 0.01532032]
Moving a ball individually through Ball.move()
Value of ball.x, ball.y: 0.336170123085 0.515320317386
Value of coords[0,:]: [ 0.33617012 0.51532032]
Преимущество здесь в том, что обновление одного массива numpy будет намного, намного быстрее, чем итерация по всем вашим объектам шара, но вы сохраните более объектно-ориентированный подход.
Только мои мысли об этом, во всяком случае ..
РЕДАКТИРОВАТЬ: Чтобы дать некоторое представление о разнице в скорости, с 1 000 000 шаров:
In [104]: %timeit coords[:,0] += 1.0
100 loops, best of 3: 11.8 ms per loop
In [105]: %timeit [item.x + 1.0 for item in balls]
1 loops, best of 3: 1.69 s per loop
Таким образом, обновление координат напрямую с использованием numpy происходит примерно на 2 порядка быстрее при использовании большого количества шаров. (при использовании 10 шаров разница меньше, чем в примере, примерно в 2 раза, а не в 150 раз)