1

I am trying to extend list type to take only integers. I did override append, setitem but it is not working. Any pointers please?

class linked_list(list):

    def __init__(self):
        self.indx = 0

   def next(self):
        self.indx += 1
        return self.__getitem__(self.indx)

    def prev(self,indx):
        self.indx -= 1
        return self.__getitem__(self.indx)


    def __append__(self,val):
        if not isinstance(val,int):
            raise Exception('only integers accepted')
        super(linked_list,self).__append__(val)


    def __getitem__(self,indx):
        try:
            return super(linked_list,self).__getitem__(indx)
        except IndexError,e:
            StopIteration()

    def __setitem__(self,key,val):
        if not isinstance(val,int):
            raise Exception('only integers accepted')

        super(linked_list,self).__setitem__(key,val)
Neil
  • 459
  • 2
  • 6
  • 16
  • 1
    Subclassing built-in types is generally a **bad** idea. You have to redefine *tons* of methods and even implement some methods not defined by `list`, otherwise you could find things like `['some', 'string'] + YourList([1,2,3])` which will defeat all your checks. – Bakuriu Mar 21 '13 at 08:04

3 Answers3

5

It's not __append__, it's simply append. Also TypeError is probably a more suitable exception.

def append(self,val):
    if not isinstance(val, int):
        raise TypeError('only integers accepted')
    super(linked_list,self).append(val)

As @TimPietzcker noted, you should also override extend and other methods appropriately

jamylak
  • 128,818
  • 30
  • 231
  • 230
3

By inheriting from collections.MutableSequence instead of list you may get away with less code. MutableSequence will automatically implement all the other list methods based on the five methods below.

from collections import MutableSequence

class IntList(MutableSequence):
    def __init__(self):
        super(IntList, self).__init__()
        self._list = []

    def __len__(self):
        return len(self._list)

    def __getitem__(self, index):
        return self._list[index]

    def __setitem__(self, index, value):
        if not isinstance(value, int):
            raise TypeError('only integers accepted')
        self._list[index] = value

    def __delitem__(self, index):
        del self._list[index]

    def insert(self, index, value):
        if not isinstance(value, int):
            raise TypeError('only integers accepted')
        self._list.insert(index, value)

On the flip side, this is not as efficient as overriding all the list methods manually -- for example, the extend method provided by MutableSequence will call __len__ and __insert__ once for each element. This can be amended by overriding any performance-sensitive methods and doing it more efficiently.

See this answer for examples of how MutableSequence uses the methods above to implement the remaining list methods.

Community
  • 1
  • 1
Lauritz V. Thaulow
  • 49,139
  • 12
  • 73
  • 92
2

You should be defining an append method, not __append__. You should also override __add__, __iadd__, insert and extend.

Zacrath
  • 521
  • 3
  • 8