36
votes

I want to implement a custom list class in Python as a subclass of list. What is the minimal set of methods I need to override from the base list class in order to get full type compatibility for all list operations?

This question suggest that at least __getslice__ needs to be overridden. From further research, also __add__ and __mul__ will be required. So I have this code:

class CustomList(list):
    def __getslice__(self,i,j):
        return CustomList(list.__getslice__(self, i, j))
    def __add__(self,other):
        return CustomList(list.__add__(self,other))
    def __mul__(self,other):
        return CustomList(list.__mul__(self,other))

The following statements work as desired, even without the overriding methods:

l = CustomList((1,2,3))
l.append(4)                       
l[0] = -1
l[0:2] = CustomList((10,11))    # type(l) is CustomList

These statements work only with the overriding methods in the above class definition:

l3 = l + CustomList((4,5,6))    # type(l3) is CustomList
l4 = 3*l                        # type(l4) is CustomList
l5 = l[0:2]                     # type(l5) is CustomList

The only thing I don't know how to achieve is making extended slicing return the right type:

l6 = l[0:2:2]                   # type(l6) is list

What do I need to add to my class definition in order to get CustomList as type of l6?

Also, are there other list operations other than extended slicing, where the result will be of list type instead of CustomList?

3
@Johnsyweb: CustomList is intended to hold data of a specific type, and will have additional parameters and methods applying to these data (which I left out for the question).silvado
Silvado, just out of curiosity, can you please give more information on CustomList and some details about the data? Inheriting from base types in Python is a VERY unappreciated practice, so maybe there is a way to do what you want to do without inheriting from list.Zaur Nasibov
BasicWOlf: Why is subclassing from base types unappreciated?Fabian
Because built-in types are optimized to work as they are. You can never assume what will be the result of overriding some of the methods and leaving other methods intact. -- Subclassing built-in types is a very common behaviour of people with Ruby background. DON'T do that in Python.Zaur Nasibov
Absolutely right. Or just items = datalist.items :)Zaur Nasibov

3 Answers

26
votes

Firstly, I recommend you follow Björn Pollex's advice (+1).

To get past this particular problem (type(l2 + l3) == CustomList), you need to implement a custom __add__():

   def __add__(self, rhs):
        return CustomList(list.__add__(self, rhs))

And for extended slicing:

    def __getitem__(self, item):
        result = list.__getitem__(self, item)
        try:
            return CustomList(result)
        except TypeError:
            return result

I also recommend...

pydoc list

...at your command prompt. You'll see which methods list exposes and this will give you a good indication as to which ones you need to override.

23
votes

You should probably read these two sections from the documentation:

Edit: In order to handle extended slicing, you should make your __getitem__-method handle slice-objects (see here, a little further down).

1
votes

Possible cut-the-gordian-knot solution: subclass UserList instead of list. (Worked for me.) That is what UserList is there for.