Custom OrderedDict that returns itself

I have the following custom class:

class MyArray (OrderedDict): def __init__ (self,*args): OrderedDict.__init__(self,*args) def __getitem__ (self, key): if not hasattr (key, '__iter__'): return OrderedDict.__getitem__ (self,key) return MyArray((k,self[k]) for k in key) 

This class does exactly what I want when I have multiple keys, but does not do what I want for individual keys.

Let me demonstrate what my code outputs:

 x = MyArray() x[0] = 3 x[1] = 4 x[2] = 5 print x[1,0,2] MyArray([(1,4),(0,3),(2,5)]) 

But then:

 print x[1] 4 

I want this to be:

 MyArray([(1,4)]) 

Here is my attempt to fix this in order to act the way I want (which led to infinite recursion):

 class MyArray (OrderedDict): def __getitem__ (self, key): if not hasattr (key, '__iter__'): return MyArray({key:OrderedDict.__getitem__ (self,key)}) return MyArray((k,OrderedDict.__getitem__ (self,k)) for k in key) 
+5
source share
2 answers

The key point here is the realization that self[k] same as self.__getitem__(k) , so you don't want to use self[k] inside __getitem__ unless you are actually trying to do some recursion. Instead, always use OrderedDict.__getitem__ (self,key) .

In an unrelated note, you generally don’t want to create a method that simply calls the same method of the parent class, that is:

 class MyArray (OrderedDict): def __init__ (self,*args): OrderedDict.__init__(self,*args) 

Just delete this method and python will call the parent class method for you, the inheritance will be awesome :).

update:

After some digging, I found that you get infinite recursion when trying to print MyArray , because OrderedDict.__repr__ calls OrderDict.items , which then calls OrderDict.__getitem__ (in the form of self[key] ), then it calls __repr__ for each of the elements. .. The problem is that you are __getitem__ to do something very different from what it does in the parent class. If you want this class to have the full functionality of the python class, you need to override each method that uses self[key] anywhere in the method. You can start with items , i.e. something like:

 def items(self): 'od.items() -> list of (key, value) pairs in od' return [(key, OrderedDict.__getitem__(self, key)) for key in self] 

When you come across similar things, it is often better to discard the subclass and just have OrderedDict as an attribute of the new class, for example:

 class MyArray(object): def __init__(self, *args): self.data = OrderedDict(*args) def __getitem__(self, key): if not hasattr (key, '__iter__'): return MyArray([(key, self.data[key])]) return MyArray([(k, self.data[k]) for k in key]) 
+5
source

Infinite recursion occurred in self.items () as specified by Bi Rico . Here is the code that works (essentially overriding self.items ())

 class MyArray (OrderedDict): def __getitem__ (self, key): if not hasattr (key, '__iter__'): return MyArray({key:OrderedDict.__getitem__ (self,key)}) return MyArray((k,OrderedDict.__getitem__ (self,k)) for k in key) def items(self): ''' called when the dictionary is printed ''' return [(k, OrderedDict.__getitem__(self, k)) for k in self] 

The code above would work without defining elements if I inherited from dict instead of OrderedDict.

0
source

Source: https://habr.com/ru/post/1238327/


All Articles