[Tutor] subclassing list -- slicing doesn't preserve type

Kent Johnson kent37 at tds.net
Tue Feb 22 14:09:43 CET 2005


Brian van den Broek wrote:
> Hi all,
> 
> I'm trying to figure out how to subclass the list built-in.
> 
> .>>> class my_list(list):
>          def __init__(self, sequence=None):
>              list.__init__(self, sequence)
>              self.spam = 1
>        
> .>>> mine = my_list((1,2,3,4))
> .>>> mine.append(42)
> .>>> mine
> [1, 2, 3, 4, 42]
> .>>> type(mine)
> <class '__main__.my_list'>
> .>>> damn = mine[1:3]
> .>>> type(damn)
> <type 'list'>
> .>>> damn
> [2, 3]
> .>>>
> 
> I had thought that by subsclassing list I got all list-like properties
> for free. Append (among others) are available for my_list instances.
> But slicing returns a list, rather than a my_list. I can see that this
> is list-like in it's way, but I'd rather have be so in mine ;-)   

The problem is that the list methods that return a new list don't know to return an object of your 
class. You will have to override those methods with a new method that converts the new list to an 
instance of my_list. Or you can use UserList which does this for you:

class my_list(list):
     def __init__(self, sequence=None):
         list.__init__(self, sequence)
         self.spam = 1

     def __getslice__(self, i, j):
         return my_list(list.__getslice__(self, i, j))

print 'Subclass list:'
mine = my_list((1,2,3,4))
mine.append(42)
print 'mine:', mine
print 'type(mine):', type(mine)
print

damn = mine[1:3]
print 'damn', damn
print 'type(damn):', type(damn)
print

from UserList import UserList
class my_list2(UserList):
     def __init__(self, sequence=None):
         UserList.__init__(self, sequence)
         self.spam = 1

print 'Subclass UserList:'
mine = my_list2((1,2,3,4))
mine.append(42)
print 'mine:', mine
print 'mine.__class__:', mine.__class__
print

damn = mine[1:3]
print 'damn', damn
print 'damn.__class__:', damn.__class__

prints:
Subclass list:
mine: [1, 2, 3, 4, 42]
type(mine): <class '__main__.my_list'>

damn [2, 3]
type(damn): <class '__main__.my_list'>

Subclass UserList:
mine: [1, 2, 3, 4, 42]
mine.__class__: __main__.my_list2

damn [2, 3]
damn.__class__: __main__.my_list2

If you decide to stick with subclassing list, UserList can still be your guide for which methods 
need wrappers. Look for the calls to self.__class__() in UserList.py.
> 
> I've read in the docs that UserList is discouraged, and in the
> Nutshell that the __getslice__, etc. special methods are depreciated.
> 
> So, how can I get slicing to preserve the my_list type? And why does
> the above class get so much for free, but not slicing?
> 
> Best, and thanks to all,
> 
> Brian vdB
> 
> 
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> http://mail.python.org/mailman/listinfo/tutor
> 




More information about the Tutor mailing list