How to subclass Python list without type problems?

Question:

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?

Asked By: silvado

||

Answers:

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).

Answered By: Björn Pollex

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.

Answered By: johnsyweb

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

Answered By: Rick Graves

As a slight modification to Johnsywebs answer. I would only convert to a CustomList if item is a slice. Otherwise CustomList(["ab"])[0] would give you CustomList(["a", "b"]) which is not what you want. Like this:

def __getitem__(self, item):
    result = list.__getitem__(self, item)
    if type(item) is slice:
        return CustomList(result)
    else:
        return result
Answered By: funnybanana18
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.