Sean Perry wrote:
C Smith wrote:

###
class Ring(list):
    def __init__(self, l):
        self[:] = l
        self._zero = 0
           def turn(self, incr=1):
        self._zero+=incr

    def __getitem__(self, i):
        return self[(i-self._zero)%len(self)]

l=Ring(range(10))
print l
l.turn(5)
print l    #same as original
print l[0] #crashes python
###


This is a classic mistake. l[0] --> l.__getitem__(l, 0), which you understand. However in __getitem__ you then call self[] which will just call __getitem__ again. and again. and again. ....


The way out is to explicitly call the parent's __getitem__.

def __getitem__(self, i):
    # list is out parent, call its method
    return list.__getitem__(self, (i - self._zero) % len(self))

Two other changes:
- in __init__(), instead of modifying self, I think it is safer to call list.__init__(). This is the usual thing do do in a subclass.
- You can change the behaviour of print by defining __repr__() or __str__().


Here is a complete version that seems to work, though you may find other list methods you need to override:

class Ring(list):
    def __init__(self, l):
        list.__init__(self, l)
        self._zero = 0

    def turn(self, incr=1):
        self._zero+=incr

    def __getitem__(self, i):
        return list.__getitem__(self, (i - self._zero) % len(self))

    def __repr__(self):
        return repr([self[i] for i in range(len(self))])


l=Ring(range(10)) print l l.turn(5) print l print l[0]


Kent

_______________________________________________
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor

Reply via email to