Last active
August 29, 2015 14:27
-
-
Save eliotb/717d5cbe9cd992c935be to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""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