Ian Ward

CKAN contributor/tech lead
Urwid author
PyRF contributor
Speedometer author

Contributing to Open Source
IASA E-Summit, 2014-05-16
Urwid Applications
Urwid Intro
Unfortunate Python
Django 1.1

Moving to Python 3
Article Tags


Ian Ward's email:
first name at this domain

wardi on OFTC, freenode and github

Locations of visitors to this page

Extending Python Lists Considered Messy

Posted on 2009-08-23, last modified 2012-04-09.

I set out to create a generic class that would extend a python list by adding a "focus". The focus is an index in the list, and it will be moved if any items are added or removed before the focus in the list. It could be used to keep track of where you are in a list that is changing while you are processing it, but I wrote it as part of making my Urwid container widgets more user-friendly.

The result is a little more complicated than I imagined.

Python lists have grown all sorts of operations that do similar things. Most of the code I have written to extend python lists is there to just translate the operations I might be interested into a sane form to work with.

It would be great if the 13 methods (7 of which I care about) that lists have to change or add to their contents all went through a single method like:

def change_contents(self, target_slice, new_data):

But unfortunately, I need to override each of the methods I'm interested in and convert their parameters into something like the above for adding my logic to each.

Those conversions are complicated by little things like the fact that math on slice start and stop parameters is dangerous. One might think that it would be safe to replace this:

some_list[x] = j

with this:

some_list[x:x+1] = [j]

And one would be correct for all values of x except -1.

This example can be fixed by replacing x+1 with x+1 or None, but what about some other situation where you're calculating x+2? It gets messy quickly.

Another example is the overloaded __getitem__ and __setitem__ methods. Here's what I mean:

some_list[x] = j   # <=>   some_list.__setitem__(x, j)
some_list[x:y] = q   # <=>   some_list.__setslice__(x, y, q)
some_list[x:y:z] = q   # <=>   some_list.__setitem__(slice(x,y,z), q)

If you know an easier way to extend Python lists, please email me (ian at this domain). Perhaps someone has already written a nice, simple to extend list wrapper class that covers all the corner cases correctly. For now, please use my code if you like.

Tags: Urwid Software Python