Skip to content

Instantly share code, notes, and snippets.

@eliotb
Last active August 29, 2015 14:27
Show Gist options
  • Save eliotb/717d5cbe9cd992c935be to your computer and use it in GitHub Desktop.
Save eliotb/717d5cbe9cd992c935be to your computer and use it in GitHub Desktop.
"""KeyedList : A list that can also be accessed using a (string) key like a dict
A mutable alternative to namedtuple, yet a lot simpler than the full featured 'namedlist' class
Intended for use like a C struct with writeable fields
"""
class KeyedList(list):
"""A list that can also be accessed using a (string) key like a dict.
Appending to the list appends a value with no key.
Sorting the list sorts the values, NOT the keys.
# Initialise it with a list of (key, value) tuples
>>> l = KeyedList([('one', 1), ('two', 2), ('foo', 23), ('bar', 9)])
>>> l
[1, 2, 23, 9]
>>> len(l)
4
# Replace the whole list using [:], (otherwise new list has no keys!)
>>> l[:] = (9,8,7,6)
>>> l
[9, 8, 7, 6]
# Access using index or key
>>> l[0]
9
>>> l['two']
8
# or by slice
>>> l[0:2]
[9, 8]
# Update using index or key
>>> l[3] = 5
>>> l['foo'] = 0
>>> l
[9, 8, 0, 5]
# Accessing items beyond the end of the list gives an IndexError
>>> l[4] = 99
Traceback (most recent call last):
...
IndexError: list assignment index out of range
>>> l['bad'] = 97
Traceback (most recent call last):
...
IndexError: bad
# It is possible to append to the list, but appended items have no keys
>>> l.append(20)
>>> l
[9, 8, 0, 5, 20]
"""
def __init__(self, kvlist):
self._keys = [kv[0] for kv in kvlist]
list.__init__(self, [kv[1] for kv in kvlist])
#self._values = [kv[1] for kv in kvlist]
def __getitem__(self, i):
if isinstance(i, (int, slice)):
return list.__getitem__(self, i)
elif self._keys and i in self._keys:
return list.__getitem__(self, self._keys.index(i))
else:
raise IndexError(str(i))
def __setitem__(self, i, val):
if isinstance(i, (int, slice)):
list.__setitem__(self, i, val)
elif self._keys and i in self._keys:
list.__setitem__(self, self._keys.index(i), val)
else:
raise IndexError(str(i))
if __name__ == '__main__':
import doctest
doctest.testmod()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment