how to do proper subclassing?

Christopher T King squirrel at WPI.EDU
Tue Aug 3 14:02:02 EDT 2004


On Tue, 3 Aug 2004, [iso-8859-1] Jonas Koelker wrote:

> I'm new to this list (/me welcomes himself).

Welcome!

> However, I want the permutation to act like a list, in
> all those cases where I don't override the operations.
> For example, assuming permfooation is the above
> permutation [1 3 4 0 2], permfooation[1:3] should
> return [3,4]. How is this done? Do I have to actually
> implement a slice-mechanism in the permutation class?

I'm not sure exactly how your permutation class is implemented, so I can't
give you a precise answer, but in general, there are three ways to do
this, each method having benefits and drawbacks:

1) Implement your class as a subclass of list.

Using this method, your class would store its list data in itself (in
self, actually), since it is effectively a list.  The __getitem__ method
needed to implement slicing will be inherited from list, and no further
work will need to be done.  This method works best if you're only altering
the behaviour of a list slightly (e.g. transforming all items in a
particular way), but may not be well suited to objects that shouldn't 
otherwise act like lists.

2) Store your data in a list, and delegate __getitem__.

Using this method, your class would store its list data in an attribute
(say self.data).  To implement slicing, you can simply define your class's
__getitem__ method like this:

 def __getitem__(self,i):
     return self.data[i]

assuming self.data contains the list data to which you want to provide 
access.  This is the easiest method if all you want to implement is 
slicing.

3) Implement __getitem__ yourself.

You should only need to do this if the data you want to slice is not 
available in a readily slicable form (perhaps you generate it on the fly).  
Implementing __getitem__ is easy; here is a general template you can use:

 def __getitem__(self,i):
     if isinstance(i,slice):
         return self.make_a_slice_and_return_a_list(i.start,i.stop,i.step)
     else:
         return self.get_an_item_at_index(i)

__getitem__ is passed either a slice object (in the case of slicing) or 
an integer (in the case of indexing).  The start, stop, and step 
attributes of the slice object return what you'd expect, or None if they 
weren't specified.  The method slice.indices(length) will compute "actual" 
slice indices for a sequence of the given length in the case of missing, 
negative, or out-of-bounds indices, returning a tuple (start, stop, 
stride).

Hope this helps.




More information about the Python-list mailing list