Python – Subclassing List to make it N-based

Have you ever wanted to use a Python list object but make the index start at 1 instead of 0? I needed to do just that today so that the indices in the list I was building would match how the spec was written.

Here’s a little class I came up with to that. It behaves exactly like a list except that the first item is at the position you specify, and the other items come after that.

Let me know if you have improvements or any dire warnings about why this is harmful somehow :-)

class NbasedList(list):
    """Overrides the list class to make it behave as if it where based at the
    specified base value instead of 0.  I.e., the first item in the list appears
    to be at index position N
    Usage:
    >>>a=NbasedList([1,2,3],1)
    >>>a[1]
    1
    """
    def __init__(self,alist,base):
        list.__init__(self,alist)
        self.base=base
    def __getitem__(self,k):
        return list.__getitem__(self,k-self.base)
    def __setitem__(self,k,value):
        list.__setitem__(self,k-self.base,value)
    def __delitem__(self,k):
        list.__delitem__(self,k-self.base)

8 Responses to “Python – Subclassing List to make it N-based”

  1. Steve Holden says:

    Why can’t the base be higher than the list’s initial length? There’s no reason, wurely, why a list of length one can’t be indexed with a base of 100?

    Also beware of using assert to raise exceptions like that, as compiling with the -O option removes assert statements from the code.

  2. Bob Ippolito says:

    I wouldn’t subclass list here, it’s not going to work correctly. You should subclass UserList.

    Slices are also broken.


    >>> a = NbasedList([1,2,3],1)
    >>> a.index(1)
    0
    >>> a[1:2]
    [2]

  3. Steve: You are right, the assert can go. I’ll update the code.

    Bob:
    UserList looks like it’s only for working with older versions of Python. Will it also help here with the broken slices?

  4. Bob Ippolito says:

    Actually after looking at the implementation of UserList again it won’t do you much good. It’s mostly just a proxy for a real list. It’s not only for working with older versions of Python necessarily, it’s just that it was the only choice before you could subclass list.

    What you want to do is implement your own class that implements all of the list methods. Subclassing list does little good because you have to override everything it does, and can cause bugs because if you forget to override something it will still work but provide incorrect results.

    Realistically you’d be better off just writing code that works the way the language does.

  5. Bob, you’re probably right. This will work for my specific need though since I only need to get and set items. I suppose to make its limited use more explicit I could raise errors for other list methods.

    …or just live with a regular Python list.

  6. While it is true that you need to override some more functions, I think you will still have less work by subclassing list then by implementing your own list. No matter how many functions you have to override it should be less then implementing all of them from scratch (for example __contains__ shouldn’t need to be overridden).

  7. sri says:
  8. Sri, that’s excellent! Good work.