I created a class that has lots of numpy arrays inside. I created a __getitem__ function that attempts to return the class with the arrays indexed like so:
MyClass[i].array1 is equivalent to MyClass.array1[i]
I would like the _ _ getitem _ _ to return references, but they are returning copies, so that assignment doesn't work.
print(MyClass[i].array1)
returns 0
MyClass[i].array1 = 10
print(MyClass[i].array1)
still returns 0
This is the _get_item_ code I'm using:
def __getitem__(self, indices):
g = copy.copy(self) # should be a shallow copy?
for key,value in g.__dict__.iteritems():
g.__dict__[key] = value[indices]
return g
I've also tried:
def __getitem__(self, indices):
g = MyClass()
for key,value in self.__dict__.iteritems():
g.__dict__[key] = value[indices]
return g
and:
def __getitem__(self, indices):
g = MyClass()
g.__dict__ = self.__dict__
for key,value in g.__dict__.iteritems():
g.__dict__[key] = value[indices]
return g
Note, this last instance does indeed seem to return references, but not the way I want. If I index my class using this last code, it performs indexing and truncating on the arrays in the original class, so:
g = MyClass[i].array1 truncates and overwrites the original array in MyClass to only have elements of index i like so:
print(len(MyClass.array1))
returns 128
print(MyClass[0].array1)
returns 0
now MyClass.array1 is a single float value, obviously not what I wanted.
I hope this is clear enough, and any help would be appreciated.
I found this but I wasn't quite sure if this applied to my problem.
-
They actually do return references - it's just that assigning to a variable rebinds the reference, instead of following the reference and mucking about with the object it refers to. You can write descriptors to get around this, but I'd first question whether it's a good idea.user2357112– user23571122013年09月12日 16:28:30 +00:00Commented Sep 12, 2013 at 16:28
1 Answer 1
This seems like a really bad idea, but it also seems like a fun problem so here is my crack at it:
class MyProxy(object):
def __init__(self, obj, key):
super(MyProxy, self).__setattr__('obj', obj)
super(MyProxy, self).__setattr__('key', key)
def __getattr__(self, name):
return getattr(self.obj, name).__getitem__(self.key)
def __setattr__(self, name, value):
return getattr(self.obj, name).__setitem__(self.key, value)
class MyClass(object):
def __init__(self, array_length):
self.array_length = array_length
def __getitem__(self, key):
if key >= self.array_length:
raise IndexError
return MyProxy(self, key)
Example:
>>> obj = MyClass(4) # replace 4 with the length of your arrays
>>> obj.array1 = [1, 2, 3, 4]
>>> obj.array2 = [5, 6, 7, 8]
>>> for c in obj:
... print c.array1, c.array2
...
1 5
2 6
3 7
4 8
>>> obj[1].array1
2
>>> obj[1].array1 = 5
>>> obj.array1
[1, 5, 3, 4]