I'm not sure about the term of this technique. I want to create a list where if I try to access an element outside the list range, the list would "loop itself". Example of the behaviour I want to achieve:
>>> musical_scale = ['C', 'D', 'E', 'F', 'G', 'A', 'B']
>>> musical_scale[2]
E
>>> musical_scale[7]
C
>>> musical_scale[-1]
B
I guess I could write a class which does this, but I thought there might be a more correct way of doing it.
Creating a subclass of List would be a pretty useful way of doing this. Something like this, perhaps:
class modList(list):
def __getitem__(self, i):
if len(self) == 0:
raise IndexError # Or do something else if you want, like return []
i = i % len(self) # self.__len__() works also
return super(modList, self).__getitem__(i) # In Python 3, super().__getitem__(i)
If you want to do slicing, it's a little more complicated, but similar. Found this while looking through StackOverflow:
def __getitem__(self, i):
if isinstance(i, int):
if len(self) == 0:
raise IndexError
i = i % len(self)
return super(modList, self).__getitem__(i) # list.__getitem__(i) works too
elif isinstance(i, slice):
if len(self) == 0:
return []
start = i.start % len(self)
stop = i.stop % len(self)
step = i.step
return super(modList, self).__getItem__(slice(start, stop, step))
else:
raise TypeError("invalid index")
Though this slice modding could give you a situation like [3:2]
, which will return an empty list. Basically slicing is hard and you'll need to decide how you want to implement it, but hopefully this is a start.
http://www.stackoverflow.com/questions/3911483/python-slice-how-to-i-know-the-python-slice-but-how-can-i-use-built-in-slice-ob
(Thanks @JonClements for all the suggestions in chat.)
EDIT: now we have some handlers for if you have an empty list. @wim suggests raising an error for single accesses, and returning []
for slices. Really it's up to you what you want to do but that seemed sensible to me, so that's what I've included in this answer.
EDIT EDIT: if you're using Python 2.x, I believe you also need to override __getslice__
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With