Suppose that you have a python class MyObject such that instances contain a list of data and that the MyObject class as a __getitem__ method defined as follows:
def __getitem__(self, index):
return self.data[index]
Suppose that we wish to modify the above __getitem__ method to something like
def __getitem__(self, index):
return self.data[my_function(index)]
where my_function is some function that transforms an alternative indexing system (say tuples of integers into the list index system - non-negative integers). Here my_function might be self.map or OtherClass.map or something else that makes the above code valid python code. We want to enable the user to change this function - including using the identity function (i.e. no conversion). This can be done easily enough.
But here is what I want to do. Suppose that I have a bunch of instances $p_1,p_2,..,p_k$ of 'MyObject' class using some map map_1 and I have another bunch of instances $q_1,q_2,...,q_t$ using some map map_2.
I want to change the map that the instances $p_1,p_2,..,p_k$ use from
map_1tomap_2. I do not want to do this by looping over each instance $p_1,p_2,..,p_k$ and setting the index map tomap_2but rather only doing $O(1)$ work (i.e. not $O(k)$ work).Then I want to have all $p_1,p_2,..,p_k,q_1,q_2,...,q_t$ instances using
map_2.Then I want to change these instances to use a new map
map_3where it again only takes the same amount of constant time to change.
I can see how to do this is C/C++ using references but not in python. The user provides the map functions and there can be many. The best I can get is as follows:
# A simple Map class to hold maps
class MapDict:
def __init__(self):
self.loaded_maps = dict()
def make_map(self, fid):
def index_funct(index):
return self.loaded_maps[fid](index)
return index_funct
# A simple class for data
class MyObject:
def __init__(self,data):
self.data = data
self._map = self._identity_map
def _identity_map(self, index):
return index
def set_map(self, input_map):
self._map = input_map
def __getitem__(self, index):
return self.data[self._map(index)]
# Create some MyObjects with sample data
p1=MyObject(range(1000))
p2=MyObject(range(1000))
q1=MyObject(range(1000))
q2=MyObject(range(1000))
#Create a class to hold the maps
map_dict = MapDict()
# Define a few map functions to use in indexing
def map1(index):
return index[0]+index[1]
def map2(index):
return index[0]*index[1]
def map3(index):
return index[0]+10*index[1]
# Load the maps into the map dict class
map_dict.loaded_maps[1] = map1
map_dict.loaded_maps[2] = map2
# Set the maps for the MyObjects
p1.set_map(map_dict.make_map(1))
p2.set_map(map_dict.make_map(1))
q1.set_map(map_dict.make_map(2))
q2.set_map(map_dict.make_map(2))
# Now change maps for p1, p2
map_dict.loaded_maps[1] = map2
# Now change maps for p1 p2 q1 q2
map_dict.loaded_maps[1] = map3
map_dict.loaded_maps[2] = map3
The problem with this approach is that I now have two instances of map3 in a dictionary rather than a single location. So if I want to change map3 to map4 for all instances using map3 then I have so change two locations. A guess that I could provide another list/dictionary on top of this to keep track but this seems overkill. Also I want to make sure that _getitem__ remains very fast (relative to the map function chosen) as I expect it to be used a lot.
I expect that there are a much better way to do this so ideas are welcome.
If I'm understanding correctly, you'd like to be able to switch the -getitem- method for a group of instances. I think having a separate class to store the mapping functions seems redundant when your MyObject class could store it for groups of its instances and dispatch the function.
Functions for remapping the index into the data:
Making a few groups with this:
Testing first mapper function and testing the changed mapper function:
Returns: