3

I have a list of Python objects, representing several classes. The classes obviously differ, but nevertheless have a couple of common attributes (with different values for each object). For example:

class Super1:
    def __init__(self, value1, value2):
        self.value1 = value1
        self.value2 = value2
        #Lot's of other stuff

class Sub1(Super1):
    def __init__(self, value1, value2, value3):
        Super1.__init__(self, value1, value2)
        self.value3 = value3
        #Lot's of stuff

class Sub2(Super1):
    def __init__(self, value1, value2, value4):
        Super1.__init__(self, value1, value2)
        self.value4 = value4
        #Lot's of stuff

objects = [Sub1(1.,2.,3.), Sub1(213.,2.,23.), Sub2(23.,10.,0.2), Sub1(3.,2.,12.)]

Now, for both convenience and performance, I would need to have to a NumPy array of all these values. I know I can read them like this:

np.array([objects[ii].value1 for ii in range(4)])

But I also need to change the values, in both the array form as well as individually within instance methods. Is it possible to somehow dynamically link the object attributes and the corresponding values in the arrays, by using pointers or something?

And no, the objects here does not have to be a list. Suggestions welcome.

3
  • It is a physical model, the objects representing different physical objects. I planned to use numpy, as I need to perform matrix algebra on the values. Commented Apr 10, 2013 at 14:22
  • why not np.array([o.value1 for o in objects])? Commented Apr 10, 2013 at 15:05
  • Ok, but that does not solve the actual issue... Commented Apr 10, 2013 at 15:34

2 Answers 2

4

Numpy arrays are "a contiguous one-dimensional segment of computer memory", so there really is no way you can create a numpy array that is made up of chunks of memory here and there.

The only possibility is to go the other way around, first create the array, then asign single element slices of that array to your objects, e.g.

class Super1(object):
    def __init__(self, value1):
        self._value1 = value1

    @property
    def value1(self):
        return self._value1[0]

    @value1.setter
    def value1(self, value):
        self._value1[0] = value

And now:

>>> a = np.arange(4)
>>> obj = [Super1(a[j:j+1]) for j in xrange(len(a))]
>>> obj[0].value1
0
>>> obj[0].value1 = 5
>>> a
array([5, 1, 2, 3])
>>> obj[2].value1
2
>>> a[2] = 8
>>> obj[2].value1
8
Sign up to request clarification or add additional context in comments.

2 Comments

Excellent, that's it! Thanks! For the record, to make your code work, I had to remove the argument value2 from the constructor and add a self. to the return command.
@HenriV Oops! Had to change those two myself to make the code work, forgot to paste the corrected code in here.
1

Use Properties if you want to modify setting attributes of objects.

This solution works with an index for an array

class Super(object):

    @property
    def value1(self):
        return self.array1[self.index]

    @value1.setter
    def value1(self, value):
        self.array1[self.index] = value

    def __init__(self, array1, index):
        self.array1 = array
        self.index = index

You will need to create the array first and then create the objects.

This is another solution with one array for an object:

class Super(object):

    @property
    def value1(self):
        return self.array[0]

    @value1.setter
    def value1(self, value):
        self.array[0] = value

    def __init__(self, array):
        self.array = array

1 Comment

I am not sure if I understood correctly, but I think I implemented your second solution, and a change in the numpy array is not reflected in the instance attributes or vice versa...?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.