0

I am trying to overload the [] operator for a list to work like a circular list.

class circularList(list):
    def __init__(self, *args):
        list.__init__(self,args)

    def __getitem__(self, key):
        return list.__getitem__(self, key%self.length)

    def __setitem__(self, key, value):
        return list.__setitem__(self, key%self.length, value)

When running this code in the sage terminal, I get the following error:

TypeError: Error when calling the metaclass bases
    list() takes at most 1 argument (3 given)
sage:     def __getitem__(self, key):
....:             return list.__getitem__(self, key%self.length)
....:     
sage:     def __setitem__(self, key, value):
....:             return list.__setitem__(self, key%self.length, value)

This would be used as follows:

circle = circularlist([1,2,3,4])

Does anyone happen to know what I am doing wrong?

Guy Person
  • 13
  • 4
  • How do you call your constructor (ie. `circularList(...)`)? – hlt Aug 20 '14 at 17:43
  • This error occurs when I define the class, I shall update the post. – Guy Person Aug 20 '14 at 17:44
  • 1
    You don't even need that `__init__` at all, first off. The superclass `__init__` will do the trick just fine, since you aren't adding any more attributes. – TheSoundDefense Aug 20 '14 at 17:45
  • 1
    He does need `__init__` because he turns the argument list into the list items (meaning that you can pass an arbitrary amount of items to the constructor instead of having to pass an iterable like to `list`) – hlt Aug 20 '14 at 17:46
  • Works for me (once I fix `self.length`). – NPE Aug 20 '14 at 17:50
  • 1
    The way you are using `circularList`, you end up creating a list similar to `[[1, 2, 3, 4]]` because you use an argument list on your constructor. Either that `*` is not needed (in which case you can drop the constructor, see @TheSoundDefense's comment), or you really want to call it as `circularList(1, 2, 3, 4)` to create a list like `[1, 2, 3, 4]` – hlt Aug 20 '14 at 18:01

1 Answers1

2

With minor fixes, this works for me using Python 2.7.1:

class circularList(list):
    def __init__(self, *args):
        list.__init__(self,args)

    def __getitem__(self, key):
        return list.__getitem__(self, key%len(self))        # Fixed self.length

    def __setitem__(self, key, value):
        return list.__setitem__(self, key%len(self), value) # Fixed self.length

circle = circularList(1,2,3,4)                              # Fixed uppercase 'L'
                                                            # pass values are argument 
                                                            # (not wrapped in a list)
print circle
for i in range(0,10):
    print i,circle[i]

Producing:

[1, 2, 3, 4]
0 1
1 2
2 3
3 4
4 1
5 2
6 3
7 4
8 1
9 2

BTW, are you aware of itertools.cycle ?

Sylvain Leroux
  • 50,096
  • 7
  • 103
  • 125