How can I make my list of lists better indexable?
<p>I'm trying to store data in a list of lists, such that each sample, which has a variety of info associated with it, all together in a list, and then store a large number of those in a list. What I have so far is:</p>

<pre><code>#!/usr/bin/env python

from operator import itemgetter # For sorting

class XaDatum (object):

    fields = {'name':0, 'ki':1, 'amt':2, 'rep': 3, 'stage':4, 'variety':5, 
              'date':6, 'comments':7}

    def __init__(self, name, ki, amt, rep=None, stage=None, variety=None, 
                 date=None, comments = None):
        for item in (name, rep, stage, variety, date, comments):
            if item is not None:
                item = str(item)
        ki = int(ki)
        amt = float(amt)
        self.datum = [name, ki, amt, rep, stage, variety, date, comments]

    def __getitem__(self, key):
        return self.datum[self.fields[key]]

    def copy(self):
        return XaDatum(self['name'], self['ki'], 
                          self['amt'], self['rep'], 
                          self['stage'], self['variety'], 
                          self['date'], self['comments'])

    def __setitem__(self, key, item): 
        if key in ['name', 'rep', 'stage', 'variety', 'date', 'comments']:
            item = str(item)
        if key == 'ki':
            item = int(item)
        if key == 'amt':
            item = float(item)
        self.datum[self.fields[key]] = item

    def __str__(self):
        return repr(self.datum)

    def show(self):
        print("{0}  {1}  {2}  {3}  {4}  {5}  {6}  {7}".format(
                self['name'], self['ki'], self['amt'], self['rep'],
                self['stage'], self['variety'], self['date'], 
                self["comments"]))


class XaData (object):

    def __init__(self):
        self.data = []
        self.count = 0

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

    def __str__(self):
        return repr(self.data)

    def append(self, name, ki, amt, rep=None, stage=None, variety=None, 
               date=None, comments=None):
        self.data.append(
            XaDatum(name, ki, amt, rep, stage, variety, date, comments))
        self.count += 1

    def show(self):
        for i in self.data:
            i.show()

    def copy(self):
        returnme = XaData()
        for item in self:
            returnme.data.append(item.copy())
        return returnme

    # Result points to the same memory! Changes to the returned
    # znoselonglist will result in changes to the original!
    def filter(self, inverse=False, min=-float('Inf'), max=float('Inf'), 
               ki_min=-float('Inf'), ki_max=float('Inf'), rep=None, stage=None,
               variety=None, date=None, comment=None):
        returnme = XaData()
        for item in self.data:
            match = ((item['amt'] &gt;= min)
                     and (item['amt'] &lt;= max)
                     and (item['ki'] &gt;= ki_min)
                     and (item['ki'] &lt;= ki_max)
                     and (rep is None or item['rep'] in rep)
                     and (stage is None or item['stage'] in stage)
                     and (variety is None or item['variety'] in variety)
                     and (date is None or item['date'] in date)
                     and (comment is None or item['comment'] in comment))
            if match ^ inverse:
                returnme.data.append(item)
        return returnme

    def sort(self, *args):
        if len(args) == 0:
            args = ('name', 'ki')
        self.data = sorted(self.data, key=itemgetter(*args))

    def unique(self, key):
        key_list = [item[key] for item in self.data]
        return sorted(list(set(key_list)))

    def unique_kis(self):
        kilist = [item['ki'] for item in self.data]
        return sorted(list(set(kilist)))

    def unique_names(self):
        namelist = [item['name'] for item in self.data]
        return sorted(list(set(namelist)))


if __name__ == "__main__":

    da = XaData()
    da.append('x00', 35, 501, stage='B', variety='V1')
    da.append('x01', 40, 309, stage='D', variety='V2')
    da.append('x02', 37, 450, stage='D', variety='V1')
    da.append('x03', 35, 470, stage='A', variety='V2')
    da.append('x04', 40, 378, stage='B', variety='V1')
    da.append('x05', 45, 770, stage='A', variety='V2')
</code></pre>

<p>If I run this I can do:</p>

<pre><code>In [1]: da.show()
x00  35  501.0  None  B  V1  None  None
x01  40  309.0  None  D  V2  None  None
x02  37  450.0  None  D  V1  None  None
x03  35  470.0  None  A  V2  None  None
x04  40  378.0  None  B  V1  None  None
x05  45  770.0  None  A  V2  None  None

In [2]: daf = da.filter(variety='V1')

In [3]: daf.show()
x00  35  501.0  None  B  V1  None  None
x02  37  450.0  None  D  V1  None  None
x04  40  378.0  None  B  V1  None  None

In [4]: daf[0]['amt'] *= 0.2

In [5]: daf.show()
x00  35  100.2  None  B  V1  None  None
x02  37  450.0  None  D  V1  None  None
x04  40  378.0  None  B  V1  None  None
</code></pre>

<p>But I can't do,</p>

<pre><code>In [6]: daf[:]['amt'] *= 0.2
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

/home/nathan/work/simo_znose/&lt;ipython console&gt; in &lt;module&gt;()

TypeError: list indices must be integers, not str
</code></pre>

<p>So my question is, how would I make slicing work? Or, alternatively, is there already a datatype or something that already does what I want?</p>

<p>Thanks in advance!</p>

<p>Nathan</p>
