title: Pythonic OOP and sklearn/numpy optimization
body: <p>I get into this issue very often, I develop my code using OOP and when I want to use numpy, sklearn modules or any other "matrix" speeded up procedures I can't figure out the best way of doing it without looping all objects again.</p>
  
  <p>For instance, I have an object called Particle which have a coordinate x:</p>
  
  <pre><code>class Particle(object):
       def __init__(self, x):
           self.x = x
  </code></pre>
  
  <p>and then I create a bunch of them like:</p>
  
  <pre><code>from numpy.random import random
  np = 100
  p = []
  points = random((np, 3))
  for i in range(np):
      p.append(Particle(points[i, :]))
  </code></pre>
  
  <p>Finally, I would like to get the distance between particles. To do so, I could use a brute force search and evaluate the norm of the distances or use an optimized module to do it faster, like:</p>
  
  <pre><code>from sklearn.metrics.pairwise import pairwise_distances
  pairwise_distances(X=points)
  </code></pre>
  
  <p>Yet, this way I have no advantage of using OOP.</p>
  
  <p>I have tried something weird like:</p>
  
  <pre><code>pairwise_distances(X=p[:].x)
  </code></pre>
  
  <p>but of course, it doesn't work.</p>
  
  <p>Another example I crossed with is related to the <a href="https://en.wikipedia.org/wiki/Lotka%E2%80%93Volterra_equations" rel="nofollow noreferrer">predator-prey model</a>. Ideally, from a numerical perspective, I would assemble each animal in a matrix form so it would be faster to solve, yet from an OOP I created an animal object with its constants within and to solve it I got into messed and slow code.</p>
  
  <p>Is there a way to work around these issues in an elegant pythonic way?
  Should I choose to program in one way over the other?</p>
  
  <p>Thank you.</p>