Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to subclass Python list without type problems?

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?

like image 699
silvado Avatar asked Nov 18 '11 09:11

silvado


3 Answers

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.

like image 67
Johnsyweb Avatar answered Oct 20 '22 18:10

Johnsyweb


You should probably read these two sections from the documentation:

  • Emulating container types
  • Additional methods for emulating sequence types (Python 2 only)

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

like image 33
Björn Pollex Avatar answered Oct 20 '22 19:10

Björn Pollex


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

like image 5
Rick Graves Avatar answered Oct 20 '22 20:10

Rick Graves